Rev 687 | Rev 693 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed
| Rev 687 | Rev 690 | ||
|---|---|---|---|
| Line 1... | Line -... | ||
| 1 | /** |
- | |
| 2 | * High level functions for bus communication and standard node behaviour. |
- | |
| 3 | * |
- | |
| 4 | * @author Andreas Fritiofson |
- | |
| 5 | * |
- | |
| 6 | * @date 2007-10-24 |
- | |
| 7 | */ |
- | |
| 8 | 1 | ||
| 9 | #include <config.h> |
- | |
| 10 | #include "stdcan.h" |
2 | #include "stdcan.h" |
| 11 | #if defined(_AVRLIB_BIOS_) |
3 | #if defined(_AVRLIB_BIOS_) |
| 12 | #include <bios.h> |
4 | #include <bios.h> |
| 13 | #define Can_Send BIOS_CanSend |
5 | #define Can_Send BIOS_CanSend |
| 14 | #else |
6 | #else |
| Line 33... | Line 25... | ||
| 33 | */ |
25 | */ |
| 34 | StdCan_Msg_t TxQ[STDCAN_TX_QUEUE_SIZE]; |
26 | StdCan_Msg_t TxQ[STDCAN_TX_QUEUE_SIZE]; |
| 35 | unsigned char TxQ_Rd_idx; /**< Transmit queue read index. */ |
27 | unsigned char TxQ_Rd_idx; /**< Transmit queue read index. */ |
| 36 | unsigned char TxQ_Wr_idx; /**< Transmit queue write index. */ |
28 | unsigned char TxQ_Wr_idx; /**< Transmit queue write index. */ |
| 37 | unsigned char TxQ_Len; /**< Number of messages in transmit queue. */ |
29 | unsigned char TxQ_Len; /**< Number of messages in transmit queue. */ |
| - | 30 | #endif |
|
| - | 31 | ||
| - | 32 | #if (STDCAN_FILTER) |
|
| - | 33 | /** |
|
| - | 34 | * The message acceptance filters. |
|
| - | 35 | */ |
|
| - | 36 | typedef struct { |
|
| - | 37 | char Active; /**< True if this filter should be used. */ |
|
| - | 38 | unsigned long Id; /**< Match if id matches the message id in all bit locations that are not masked. */ |
|
| - | 39 | unsigned long Mask; /**< Each bit specifies if the corresponding id bit must match (mask[n] = 1) or is Don't Care (mask[n] = 0). */ |
|
| - | 40 | } StdCan_Filter_t; |
|
| - | 41 | ||
| - | 42 | StdCan_Filter_t RxFilters[STDCAN_NUM_FILTERS]; |
|
| 38 | #endif |
43 | #endif |
| 39 | 44 | ||
| 40 | /** |
45 | /** |
| 41 | * CAN message callback. |
46 | * CAN message callback. |
| 42 | * Callback for when a message is received from the lower |
47 | * Callback for when a message is received from the lower |
| 43 | * layer (BIOS or CAN driver). |
48 | * layer (BIOS or CAN driver). |
| 44 | */ |
49 | */ |
| 45 | void Can_Process(Can_Message_t* msg) |
50 | void Can_Process(Can_Message_t* msg) |
| 46 | { |
51 | { |
| 47 | unsigned char n; |
52 | unsigned char n; |
| 48 | /* Check if there is room on the queue. */ |
53 | /* Check if there is room on the queue. */ |
| 49 | if (RxQ_Len < STDCAN_RX_QUEUE_SIZE) { |
54 | if (RxQ_Len < STDCAN_RX_QUEUE_SIZE) { |
| - | 55 | ||
| - | 56 | #if (STDCAN_FILTER) |
|
| - | 57 | /* Try to match each filter in turn. */ |
|
| - | 58 | for (n = 0; n < STDCAN_NUM_FILTERS; n++) { |
|
| - | 59 | if (RxFilters[n].Active && !((msg->Id ^ RxFilters[n].Id) & RxFilters[n].Mask)) { |
|
| - | 60 | RxQ[RxQ_Wr_idx].Match = n; |
|
| - | 61 | break; |
|
| - | 62 | } |
|
| - | 63 | } |
|
| - | 64 | ||
| - | 65 | if (n == STDCAN_NUM_FILTERS) return; // No match found, discard message. |
|
| - | 66 | #endif |
|
| 50 | /* Copy the message from lower layer into the queue. */ |
67 | /* Copy the message from lower layer into the queue. */ |
| 51 | RxQ[RxQ_Wr_idx].Id = msg->Id; |
68 | RxQ[RxQ_Wr_idx].Id = msg->Id; |
| 52 | RxQ[RxQ_Wr_idx].Length = msg->DataLength; |
69 | RxQ[RxQ_Wr_idx].Length = msg->DataLength; |
| 53 | //TODO: This should be guarded against invalid DataLength. |
70 | //TODO: This should be guarded against invalid DataLength. |
| 54 | for (n = 0; n < RxQ[RxQ_Wr_idx].Length; n++) { |
71 | for (n = 0; n < RxQ[RxQ_Wr_idx].Length; n++) { |
| Line 59... | Line 76... | ||
| 59 | RxQ_Len++; |
76 | RxQ_Len++; |
| 60 | } else { |
77 | } else { |
| 61 | /* Overflow, just drop the new message. In the future, some |
78 | /* Overflow, just drop the new message. In the future, some |
| 62 | * form of priority scheme could be used to drop another |
79 | * form of priority scheme could be used to drop another |
| 63 | * message in the queue. |
80 | * message in the queue. |
| 64 | */ |
81 | */ |
| 65 | } |
82 | } |
| 66 | } |
83 | } |
| 67 | 84 | ||
| 68 | StdCan_Ret_t StdCan_Init(Node_Desc_t* node_desc) |
85 | StdCan_Ret_t StdCan_Init(Node_Desc_t* node_desc) |
| 69 | { |
86 | { |
| 70 | StdCan_Ret_t retval; |
87 | StdCan_Ret_t retval; |
| 71 | 88 | ||
| 72 | /* Reset all queue variables. */ |
89 | /* Reset all queue variables. */ |
| 73 | RxQ_Rd_idx = 0; |
90 | RxQ_Rd_idx = 0; |
| 74 | RxQ_Wr_idx = 0; |
91 | RxQ_Wr_idx = 0; |
| 75 | RxQ_Len = 0; |
92 | RxQ_Len = 0; |
| - | 93 | #if (STDCAN_TX_QUEUE_SIZE > 1) |
|
| 76 | TxQ_Rd_idx = 0; |
94 | TxQ_Rd_idx = 0; |
| 77 | TxQ_Wr_idx = 0; |
95 | TxQ_Wr_idx = 0; |
| 78 | TxQ_Len = 0; |
96 | TxQ_Len = 0; |
| - | 97 | #endif |
|
| 79 | 98 | ||
| 80 | #if defined(_AVRLIB_BIOS_) |
99 | #if defined(_AVRLIB_BIOS_) |
| 81 | /* Initialize BIOS' interface for CAN. */ |
100 | /* Initialize BIOS' interface for CAN. */ |
| 82 | BIOS_CanCallback = Can_Process; |
101 | BIOS_CanCallback = Can_Process; |
| 83 | retval = StdCan_Ret_OK; |
102 | retval = StdCan_Ret_OK; |
| Line 122... | Line 141... | ||
| 122 | 141 | ||
| 123 | StdCan_Ret_t StdCan_Put(StdCan_Msg_t* msg) |
142 | StdCan_Ret_t StdCan_Put(StdCan_Msg_t* msg) |
| 124 | { |
143 | { |
| 125 | Can_Message_t Can_Msg; |
144 | Can_Message_t Can_Msg; |
| 126 | unsigned char n; |
145 | unsigned char n; |
| 127 | 146 | ||
| 128 | /* Validate message. */ |
147 | /* Validate message. */ |
| 129 | if ((unsigned)msg->Length > 8) return StdCan_Ret_DataErr; |
148 | if ((unsigned)msg->Length > 8) return StdCan_Ret_DataErr; |
| 130 | 149 | ||
| 131 | /* Copy message directly to lower layer until a proper |
150 | /* Copy message directly to lower layer until a proper |
| 132 | * queue has been implemented. |
151 | * queue has been implemented. |
| Line 163... | Line 182... | ||
| 163 | | (NODE_ID << CAN_SHIFT_NMT_SID); |
182 | | (NODE_ID << CAN_SHIFT_NMT_SID); |
| 164 | 183 | ||
| 165 | /* Try to send it. */ |
184 | /* Try to send it. */ |
| 166 | Can_Send(&Heartbeat); |
185 | Can_Send(&Heartbeat); |
| 167 | } |
186 | } |
| - | 187 | ||
| - | 188 | #if (STDCAN_FILTER) |
|
| - | 189 | StdCan_Ret_t StdCan_EnableFilter(unsigned char filter, unsigned long id, unsigned long mask) |
|
| - | 190 | { |
|
| - | 191 | if (filter < STDCAN_NUM_FILTERS) { |
|
| - | 192 | RxFilters[filter].Id = id; |
|
| - | 193 | RxFilters[filter].Mask = mask; |
|
| - | 194 | RxFilters[filter].Active = 1; |
|
| - | 195 | return StdCan_Ret_OK; |
|
| - | 196 | } else { |
|
| - | 197 | return StdCan_Ret_DataErr; |
|
| - | 198 | } |
|
| - | 199 | } |
|
| - | 200 | ||
| - | 201 | StdCan_Ret_t StdCan_DisableFilter(unsigned char filter) |
|
| - | 202 | { |
|
| - | 203 | if (filter < STDCAN_NUM_FILTERS) { |
|
| - | 204 | RxFilters[filter].Active = 0; |
|
| - | 205 | return StdCan_Ret_OK; |
|
| - | 206 | } else { |
|
| - | 207 | return StdCan_Ret_DataErr; |
|
| - | 208 | } |
|
| - | 209 | } |
|
| - | 210 | #endif |
|