Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-src by
Revision 637:ed69428d4850, committed 2015-12-22
- Comitter:
- jaerts
- Date:
- Tue Dec 22 13:22:16 2015 +0000
- Parent:
- 636:2eeeebd316f9
- Commit message:
- Add very shady LPC1768 CAN Filter implementation
Changed in this revision
| targets/hal/TARGET_NXP/TARGET_LPC176X/can_api.c | Show annotated file Show diff for this revision Revisions of this file |
--- a/targets/hal/TARGET_NXP/TARGET_LPC176X/can_api.c Thu Nov 26 11:20:41 2015 +0000
+++ b/targets/hal/TARGET_NXP/TARGET_LPC176X/can_api.c Tue Dec 22 13:22:16 2015 +0000
@@ -63,6 +63,9 @@
};
typedef struct CANMsg CANMsg;
+static int CAN_std_cnt = 0;
+static int CAN_ext_cnt = 0;
+
static uint32_t can_irq_ids[CAN_NUM] = {0};
static can_irq_handler irq_handler;
@@ -121,7 +124,129 @@
}
int can_filter(can_t *obj, uint32_t id, uint32_t mask, CANFormat format, int32_t handle) {
- return 0; // not implemented
+ uint32_t buf0, buf1;
+ int cnt1, cnt2, bound1;
+
+ /* Acceptance Filter Memory full */
+ if ((((CAN_std_cnt + 1) >> 1) + CAN_ext_cnt) >= 512)
+ return 0; /* error: objects full */
+
+ /* Setup Acceptance Filter Configuration
+ Acceptance Filter Mode Register = Off */
+ LPC_CANAF->AFMR = 0x00000001;
+
+ if (format == CANStandard) { /* Add mask for standard identifiers */
+ id |= (int)obj->index << 13; /* Add controller number */
+ id &= 0x0000F7FF; /* Mask out 16-bits of ID */
+
+ /* Move all remaining extended mask entries one place up
+ if new entry will increase standard ID filters list */
+ if ((CAN_std_cnt & 0x0001) == 0 && CAN_ext_cnt != 0) {
+ cnt1 = (CAN_std_cnt >> 1);
+ bound1 = CAN_ext_cnt;
+ buf0 = LPC_CANAF_RAM->mask[cnt1];
+ while (bound1--) {
+ cnt1++;
+ buf1 = LPC_CANAF_RAM->mask[cnt1];
+ LPC_CANAF_RAM->mask[cnt1] = buf0;
+ buf0 = buf1;
+ }
+ }
+
+ if (CAN_std_cnt == 0) { /* For entering first ID */
+ LPC_CANAF_RAM->mask[0] = 0x0000FFFF | (id << 16);
+ } else if (CAN_std_cnt == 1) { /* For entering second ID */
+ if ((LPC_CANAF_RAM->mask[0] >> 16) > id)
+ LPC_CANAF_RAM->mask[0] = (LPC_CANAF_RAM->mask[0] >> 16) | (id << 16);
+ else
+ LPC_CANAF_RAM->mask[0] = (LPC_CANAF_RAM->mask[0] & 0xFFFF0000) | id;
+ } else {
+ /* Find where to insert new ID */
+ cnt1 = 0;
+ cnt2 = CAN_std_cnt;
+ bound1 = (CAN_std_cnt - 1) >> 1;
+ while (cnt1 <= bound1) { /* Loop through standard existing IDs */
+ if ((LPC_CANAF_RAM->mask[cnt1] >> 16) > id) {
+ cnt2 = cnt1 * 2;
+ break;
+ }
+ if ((LPC_CANAF_RAM->mask[cnt1] & 0x0000FFFF) > id) {
+ cnt2 = cnt1 * 2 + 1;
+ break;
+ }
+ cnt1++; /* cnt1 = U32 where to insert new ID */
+ } /* cnt2 = U16 where to insert new ID */
+
+ if (cnt1 > bound1) { /* Adding ID as last entry */
+ if ((CAN_std_cnt & 0x0001) == 0) /* Even number of IDs exists */
+ LPC_CANAF_RAM->mask[cnt1] = 0x0000FFFF | (id << 16);
+ else /* Odd number of IDs exists */
+ LPC_CANAF_RAM->mask[cnt1] = (LPC_CANAF_RAM->mask[cnt1] & 0xFFFF0000) | id;
+ } else {
+ buf0 = LPC_CANAF_RAM->mask[cnt1]; /* Remember current entry */
+ if ((cnt2 & 0x0001) == 0) /* Insert new mask to even address */
+ buf1 = (id << 16) | (buf0 >> 16);
+ else /* Insert new mask to odd address */
+ buf1 = (buf0 & 0xFFFF0000) | id;
+
+ LPC_CANAF_RAM->mask[cnt1] = buf1; /* Insert mask */
+
+ bound1 = CAN_std_cnt >> 1;
+ /* Move all remaining standard mask entries one place up */
+ while (cnt1 < bound1) {
+ cnt1++;
+ buf1 = LPC_CANAF_RAM->mask[cnt1];
+ LPC_CANAF_RAM->mask[cnt1] = (buf1 >> 16) | (buf0 << 16);
+ buf0 = buf1;
+ }
+
+ if ((CAN_std_cnt & 0x0001) == 0) /* Even number of IDs exists */
+ LPC_CANAF_RAM->mask[cnt1] = (LPC_CANAF_RAM->mask[cnt1] & 0xFFFF0000) | (0x0000FFFF);
+ }
+ }
+ CAN_std_cnt++;
+ } else { /* Add mask for extended identifiers */
+ id |= (int)obj->index << 29; /* Add controller number */
+
+ cnt1 = ((CAN_std_cnt + 1) >> 1);
+ cnt2 = 0;
+ while (cnt2 < CAN_ext_cnt) { /* Loop through extended existing masks */
+ if (LPC_CANAF_RAM->mask[cnt1] > id)
+ break;
+ cnt1++; /* cnt1 = U32 where to insert new mask */
+ cnt2++;
+ }
+
+ buf0 = LPC_CANAF_RAM->mask[cnt1]; /* Remember current entry */
+ LPC_CANAF_RAM->mask[cnt1] = id; /* Insert mask */
+
+ CAN_ext_cnt++;
+
+ bound1 = CAN_ext_cnt - 1;
+ /* Move all remaining extended mask entries one place up */
+ while (cnt2 < bound1) {
+ cnt1++;
+ cnt2++;
+ buf1 = LPC_CANAF_RAM->mask[cnt1];
+ LPC_CANAF_RAM->mask[cnt1] = buf0;
+ buf0 = buf1;
+ }
+ }
+
+ /* Calculate std ID start address (buf0) and ext ID start address (buf1) */
+ buf0 = ((CAN_std_cnt + 1) >> 1) << 2;
+ buf1 = buf0 + (CAN_ext_cnt << 2);
+
+ /* Setup acceptance filter pointers */
+ LPC_CANAF->SFF_sa = 0;
+ LPC_CANAF->SFF_GRP_sa = buf0;
+ LPC_CANAF->EFF_sa = buf0;
+ LPC_CANAF->EFF_GRP_sa = buf1;
+ LPC_CANAF->ENDofTable = buf1;
+
+ LPC_CANAF->AFMR = 0x00000000; /* Use acceptance filter */
+
+ return 1;
}
static inline void can_irq(uint32_t icr, uint32_t index) {
