Revision: 1323 Author: bvwelch Date: Mon Sep 14 18:57:58 2009 Log: support standard and extended CAN frames, using the socket-CAN ID approach
http://code.google.com/p/jallib/source/detail?r=1323 Modified: /trunk/include/peripheral/can/can_legacy.jal ======================================= --- /trunk/include/peripheral/can/can_legacy.jal Wed Aug 26 14:18:49 2009 +++ /trunk/include/peripheral/can/can_legacy.jal Mon Sep 14 18:57:58 2009 @@ -10,8 +10,61 @@ -- has many enhanced features, but defaults on power-up to a 'legacy' mode. -- -- N.B. This library has only been tested so far with the 18F2585 device. +-- + + +-- the CAN ID uses the same 32-bit unsigned int format as the socket-CAN C library +-- bit 0-28 : CAN identifier (11/29 bit) +-- bit 29 : error frame flag (0 = data frame, 1 = error frame) +-- bit 30 : remote transmission request flag (1 = rtr frame) +-- bit 31 : frame format flag (0 = standard 11 bit, 1 = extended 29 bit) +-- + +procedure can_encode_rtr_id(dword in out can_id) is + pragma inline + var bit rtr at can_id:30 + rtr = 1 +end procedure + +procedure can_encode_ext_id(dword in out can_id) is + pragma inline + var bit ext at can_id:31 + ext = 1 +end procedure + +procedure can_encode_std_id(dword in out can_id) is + pragma inline + var bit ext at can_id:31 + ext = 0 +end procedure + +-- FIXME: will we ever need this? +function can_is_error_id(dword in can_id) return bit is + pragma inline + var bit error at can_id:29 + return error +end function + +function can_is_rtr_id(dword in can_id) return bit is + pragma inline + var bit rtr at can_id:30 + return rtr +end function + +function can_is_ext_id(dword in can_id) return bit is + pragma inline + var bit ext at can_id:31 + return ext +end function + +function can_is_std_id(dword in can_id) return bit is + pragma inline + var bit ext at can_id:31 + return ext == 0 +end function procedure can_reset() is + pragma inline ECANCON = 0 -- ECAN will operate in legacy CAN mode CANCON = 0x80 -- config mode end procedure @@ -20,6 +73,7 @@ -- see datasheet for details. -- N.B. The chip must already be in 'configuration mode'. procedure can_set_config(byte in p1, byte in p2, byte in p3) is + pragma inline BRGCON1 = p1 BRGCON2 = p2 BRGCON3 = p3 @@ -28,6 +82,7 @@ -- set RX acceptance mask for buffer RXB0 -- N.B. calling with 0,0,0,0 will pass all messages procedure can_set_rxb0_mask(byte in sidh, byte in sidl, byte in eidh, byte in eidl) is + pragma inline RXM0SIDH = sidh RXM0SIDL = sidl RXM0EIDH = eidh @@ -36,6 +91,7 @@ -- set RXB0 acceptance filter #0 procedure can_set_rxb0_filter0(byte in sidh, byte in sidl, byte in eidh, byte in eidl) is + pragma inline RXF0SIDH = sidh RXF0SIDL = sidl RXF0EIDH = eidh @@ -44,6 +100,7 @@ -- set RXB0 acceptance filter #1 procedure can_set_rxb0_filter1(byte in sidh, byte in sidl, byte in eidh, byte in eidl) is + pragma inline RXF1SIDH = sidh RXF1SIDL = sidl RXF1EIDH = eidh @@ -53,6 +110,7 @@ -- set RX acceptance mask for buffer RXB1 -- N.B. calling with 0,0,0,0 will pass all messages procedure can_set_rxb1_mask(byte in sidh, byte in sidl, byte in eidh, byte in eidl) is + pragma inline RXM1SIDH = sidh RXM1SIDL = sidl RXM1EIDH = eidh @@ -61,6 +119,7 @@ -- set RXB1 acceptance filter #2 procedure can_set_rxb1_filter2(byte in sidh, byte in sidl, byte in eidh, byte in eidl) is + pragma inline RXF2SIDH = sidh RXF2SIDL = sidl RXF2EIDH = eidh @@ -69,6 +128,7 @@ -- set RXB1 acceptance filter #3 procedure can_set_rxb1_filter3(byte in sidh, byte in sidl, byte in eidh, byte in eidl) is + pragma inline RXF3SIDH = sidh RXF3SIDL = sidl RXF3EIDH = eidh @@ -77,6 +137,7 @@ -- set RXB1 acceptance filter #4 procedure can_set_rxb1_filter4(byte in sidh, byte in sidl, byte in eidh, byte in eidl) is + pragma inline RXF4SIDH = sidh RXF4SIDL = sidl RXF4EIDH = eidh @@ -85,19 +146,42 @@ -- set RXB1 acceptance filter #5 procedure can_set_rxb1_filter5(byte in sidh, byte in sidl, byte in eidh, byte in eidl) is + pragma inline RXF5SIDH = sidh RXF5SIDL = sidl RXF5EIDH = eidh RXF5EIDL = eidl end procedure --- send standard 11-bit CAN frame +-- send CAN frame -- Non-blocking -- function returns immediately if buffer is busy (in-use) -- FIXME. this is ugly code -function can_send(byte in buf_no, word in std_id, byte in buf[8], byte in len) return bit is - var bit stat +function can_send(byte in buf_no, dword in can_id, byte in buf[8], byte in len) return bit is + var bit can_id_rtr at can_id:30 + var bit can_id_ext at can_id:31 + var bit stat, rtr, exid var byte r_base, i, v - var word sidh, sidl + var dword sidh, sidl, eidh, eidl, dtmp + + exid = can_id_ext + rtr = can_id_rtr + + -- bullet-proofing + if exid then + can_id = can_id & 0x1FFFFFFF + else + can_id = can_id & 0x7FF + end if + + -- bullet-proofing + if len > 8 then + len = 8 + end if + + -- Remote Request frame? set RTR bit + if rtr then + len = len | 0x40 + end if if buf_no == 0 then r_base = 0x40 @@ -123,14 +207,40 @@ POSTINC1 = 0 -- N.B. SIDH and SIDL bit-layout are weird (see datasheet) - sidh = std_id >> 3 - sidl = std_id & 7 - sidl = sidl << 5 + -- tip: to allow both 11-bit and 29-bit on same bus and same controller, + -- the 29-bit is broken into an 11-bit section and an 18-bit section. + + -- we'll do the 18-bit section first + + if exid then + eidl = can_id & 0xff + can_id = can_id >> 8 + + eidh = can_id & 0xff + can_id = can_id >> 8 + + sidl = can_id & 3 + can_id = can_id >> 2 + + -- set the EXIDEN bit + sidl = sidl | 8 + else + sidl = 0 + end if + + -- now the 11-bit section. + dtmp = can_id & 7 + can_id = can_id >> 3 + dtmp = dtmp << 5 + sidl = sidl | dtmp + + -- the final 8 bits. + sidh = can_id POSTINC1 = byte(sidh) POSTINC1 = byte(sidl) - POSTINC1 = 0 - POSTINC1 = 0 + POSTINC1 = byte(eidh) + POSTINC1 = byte(eidl) POSTINC1 = len for 8 using i loop POSTINC1 = buf[i] @@ -142,14 +252,17 @@ return 1 end function --- receive standard 11-bit CAN frame +-- receive CAN frame, sets can_id flag bits as to standard/extended, error, and remote. -- Non-blocking -- function returns immediately if no message is available. --- FIXME. N. B. This routine will automatically discard any extended frames! -- FIXME. this is ugly code -function can_receive(byte in buf_no, word out std_id, byte out buf[8], byte out len) return bit is - var bit rtr, ide, stat, ex +function can_receive(byte in buf_no, dword out can_id, byte out buf[8], byte out len) return bit is + var bit can_id_error at can_id:29 + var bit can_id_rtr at can_id:30 + var bit can_id_ext at can_id:31 + var bit rtr, exid, stat, ex var byte r_base, i, v - var byte sidh, sidl + var byte sidh, sidl, eidh, eidl + var dword dtmp if buf_no == 0 then r_base = 0x60 @@ -169,42 +282,69 @@ return 0 end if - -- N.B. At this point we have a message. We must read it, - -- even if we decide to discard it later. - - rtr = v & 8 + -- N.B. At this point we have a message. + sidh = POSTINC1 sidl = POSTINC1 - v = POSTINC1 -- skip EIDH - v = POSTINC1 -- skip EIDL + eidh = POSTINC1 + eidl = POSTINC1 len = POSTINC1 for 8 using i loop buf[i] = POSTINC1 end loop - -- FIXME, side-effects to writing all bits of RXBnCON register + -- clear the RXFUL bit FSR1L = r_base - INDF1 = 0 - - -- Remote Request frames do not include any data - if rtr != 0 then - len = 0 - end if - - -- discard 'extended frames' - -- FIXME - ide = sidl & 8 - if ide != 0 then - return 0 + v = INDF1 & 0x7F + INDF1 = v + + rtr = len & 0x40 + len = len & 0x0F + + -- bullet-proofing + if len > 8 then + len = 8 end if - -- form the 11-bit ID. See datasheet. - std_id = word(sidh) - std_id = std_id << 3 - sidl = sidl >> 5 - std_id = std_id | word(sidl) - + -- is this an extended frame? save this info for later. + exid = sidl & 8 + + -- form the CAN ID, watch out for weird hardware bits. See datasheet. + -- tip: to allow both 11-bit and 29-bit on same bus and same controller, + -- the 29-bit is broken into an 11-bit section and an 18-bit section. + + -- start of 11-bit section. + -- 8 highest bits + can_id = dword(sidh) + + -- next 3 bits. OK that's 11 bits so far. + -- SIDL has a weird layout. see datasheet. + can_id = can_id << 3 + dtmp = dword(sidl) >> 5 + can_id = can_id | dtmp + + if exid then + + -- start of 18-bit section. + -- 2 bits. + can_id = can_id << 2 + dtmp = dword(sidl) & 3 + can_id = can_id | dtmp + + -- next 8 bits + can_id = can_id << 8 + can_id = can_id | dword(eidh) + + -- final 8 bits. 11+18=29 bits. + can_id = can_id << 8 + can_id = can_id | dword(eidl) + + end if + + can_id_ext = exid + can_id_rtr = rtr + can_id_error = 0 return 1 end function --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "jallib" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/jallib?hl=en -~----------~----~----~----~------~----~------~--~---
