Esempio n. 1
0
bool CAN_setup_filter(const can_std_id_t *std_id_list,           uint16_t sid_cnt,
                      const can_std_grp_id_t *std_group_id_list, uint16_t sgp_cnt,
                      const can_ext_id_t *ext_id_list,           uint16_t eid_cnt,
                      const can_ext_grp_id_t *ext_group_id_list, uint16_t egp_cnt)
{
    bool ok = true;

    // Count of standard IDs must be even
    if (sid_cnt & 1) {
        return false;
    }

    LPC_CANAF->AFMR = afmr_disabled;
    {
        /* Filter RAM is after the FulLCAN entries */
        uint8_t *can_ram_base = (uint8_t*)&(LPC_CANAF_RAM->mask[0]);
        uint8_t *filter_ram_base = can_ram_base + LPC_CANAF->SFF_sa; // Our filter RAM is after FullCAN entries

        /* FullCAN entries take up 2 bytes each at beginning RAM, and 12-byte sections at the end */
        uint8_t *end  = can_ram_base + sizeof(LPC_CANAF_RAM->mask) -
                        ( sizeof(can_fullcan_msg_t) * CAN_fullcan_get_num_entries());
        uint8_t *ptr = filter_ram_base;

        #define CAN_add_filter_list(list, ptr, end, cnt, entry_size)  \
                do { if (NULL != list) {                              \
                     if (ptr + (cnt * entry_size) < end) {            \
                         memcpy(ptr, list, (cnt * entry_size));       \
                         ptr += (cnt * entry_size);                   \
                } else { ok = false; } } } while(0)

        /* The sa (start addresses) are byte address offset from CAN RAM
         * and must be 16-bit (WORD) aligned
         * LPC_CANAF->SFF_sa should already be setup by FullCAN if used, or
         * set to zero by the can init function.
         */
        CAN_add_filter_list(std_id_list, ptr, end, sid_cnt, sizeof(can_std_id_t));

        LPC_CANAF->SFF_GRP_sa = (ptr - can_ram_base);
        CAN_add_filter_list(std_group_id_list, ptr, end, sgp_cnt, sizeof(can_std_grp_id_t));

        LPC_CANAF->EFF_sa = (ptr - can_ram_base);
        CAN_add_filter_list(ext_id_list, ptr, end, eid_cnt, sizeof(can_ext_id_t));

        LPC_CANAF->EFF_GRP_sa = (ptr - can_ram_base);
        CAN_add_filter_list(ext_group_id_list, ptr, end, egp_cnt, sizeof(can_ext_grp_id_t));

        /* End of table is where the FullCAN messages are stored */
        LPC_CANAF->ENDofTable = (ptr - can_ram_base);
    }

    /* If there was no FullCAN entry, then SFF_sa will be zero.
     * If it was zero, we just enable the AFMR, but if it was not zero, that means
     * FullCAN entry was added, so we restore AMFR to fullcan enable
     */
    LPC_CANAF->AFMR = (0 == LPC_CANAF->SFF_sa) ? afmr_enabled : afmr_fullcan;

    return ok;
}
Esempio n. 2
0
bool CAN_setup_filter(const can_std_id_t *std_id_list,           uint16_t sid_cnt,
                      const can_std_grp_id_t *std_group_id_list, uint16_t sgp_cnt,
                      const can_ext_id_t *ext_id_list,           uint16_t eid_cnt,
                      const can_ext_grp_id_t *ext_group_id_list, uint16_t egp_cnt)
{
    bool ok = true;
    uint32_t i = 0;
    uint32_t temp32 = 0;

    // Count of standard IDs must be even
    if (sid_cnt & 1) {
        return false;
    }

    LPC_CANAF->AFMR = afmr_disabled;
    do {
        /* Filter RAM is after the FulLCAN entries */
        uint32_t can_ram_base_addr = (uint32_t) &(LPC_CANAF_RAM->mask[0]);

        /* FullCAN entries take up 2 bytes each at beginning RAM, and 12-byte sections at the end */
        const uint32_t can_ram_end_addr  = can_ram_base_addr + sizeof(LPC_CANAF_RAM->mask) -
                        ( sizeof(can_fullcan_msg_t) * CAN_fullcan_get_num_entries());

        /* Our filter RAM is after FullCAN entries */
        uint32_t *ptr = (uint32_t*) (can_ram_base_addr + LPC_CANAF->SFF_sa);

        /* macro to swap top and bottom 16-bits of 32-bit DWORD */
        #define CAN_swap32(t32) do {                    \
                        t32 = (t32 >> 16) | (t32 << 16);\
        } while (0)

        /**
         * Standard ID list and group list need to swapped otherwise setting the wrong
         * filter will make the CAN ISR go into a loop for no apparent reason.
         * It looks like the filter data is motorolla big-endian format.
         * See "configuration example 5" in CAN chapter.
         */
        #define CAN_add_filter_list(list, ptr, end, cnt, entry_size, swap)  \
                do { if (NULL != list) {                              \
                     if ((uint32_t)ptr + (cnt * entry_size) < end) {  \
                         for (i = 0; i < (cnt * entry_size)/4; i++) { \
                             if(swap) {                               \
                                 temp32 = ((uint32_t*)list) [i];      \
                                 CAN_swap32(temp32);                  \
                                 ptr[i] = temp32;                     \
                             }                                        \
                             else {                                   \
                                 ptr[i] = ((uint32_t*)list) [i];      \
                             }                                        \
                         }                                            \
                         ptr += (cnt * entry_size)/4;                 \
                } else { ok = false; } } } while(0)

        /* The sa (start addresses) are byte address offset from CAN RAM
         * and must be 16-bit (WORD) aligned
         * LPC_CANAF->SFF_sa should already be setup by FullCAN if used, or
         * set to zero by the can init function.
         */
        CAN_add_filter_list(std_id_list, ptr, can_ram_end_addr, sid_cnt, sizeof(can_std_id_t), true);

        LPC_CANAF->SFF_GRP_sa = ((uint32_t)ptr - can_ram_base_addr);
        CAN_add_filter_list(std_group_id_list, ptr, can_ram_end_addr, sgp_cnt, sizeof(can_std_grp_id_t), true);

        LPC_CANAF->EFF_sa = ((uint32_t)ptr - can_ram_base_addr);
        CAN_add_filter_list(ext_id_list, ptr, can_ram_end_addr, eid_cnt, sizeof(can_ext_id_t), false);

        LPC_CANAF->EFF_GRP_sa = ((uint32_t)ptr - can_ram_base_addr);
        CAN_add_filter_list(ext_group_id_list, ptr, can_ram_end_addr, egp_cnt, sizeof(can_ext_grp_id_t), false);

        /* End of table is where the FullCAN messages are stored */
        LPC_CANAF->ENDofTable = ((uint32_t)ptr - can_ram_base_addr);
    } while(0);

    /* If there was no FullCAN entry, then SFF_sa will be zero.
     * If it was zero, we just enable the AFMR, but if it was not zero, that means
     * FullCAN entry was added, so we restore AMFR to fullcan enable
     */
    LPC_CANAF->AFMR = (0 == LPC_CANAF->SFF_sa) ? afmr_enabled : afmr_fullcan;

    return ok;
}