Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
11CXX_rom_can.c
Go to the documentation of this file.
1
36#ifdef TARGET_LPC11Cxx
37
38#include "11CXX_rom_driver_CAN.h"
39#include "can.h"
40
41typedef struct _ROM {
42 const unsigned p_usbd;
43 const unsigned p_clib;
44 const CAND *pCAND;
45} ROM;
46
48ROM **rom = (ROM **)0x1fff1ff8;
49
50static const int RX_MSG_OBJ_NUM = 1;
51static const int TX_MSG_OBJ_NUM = 2;
52
54typedef struct lpc11crom_can_priv
55{
56 CanPriv canPriv;
57 char txPending;
58} LPC11CRomCanPriv;
59
61static LPC11CRomCanPriv can_private[1] =
62{
63 {
64 .txPending = 0
65 }
66};
67
69void CAN_IRQHandler (void){
70 (*rom)->pCAND->isr();
71}
72
73static int lpc11crom_can_init(devtab_t *dev);
74static void ignore_dev_function(devtab_t *dev);
75static void lpc11crom_can_tx_msg(devtab_t *dev);
76
77static void CAN_rx(uint8_t msg_obj_num);
78static void CAN_tx(uint8_t msg_obj_num);
79static void CAN_error(uint32_t error_info);
80
82static const CAN_CALLBACKS callbacks = {
83 CAN_rx,
84 CAN_tx,
85 CAN_error,
86 NULL,
87 NULL,
88 NULL,
89 NULL,
90 NULL,
91};
92
93
95const uint32_t ClkInitTable125[2] = {
96 0x00000000UL, // CANCLKDIV
97 0x00001C57UL // CAN_BTR
98};
99
101static const uint32_t ClkInitTable250[2] = {
102 0x00000000UL, // CANCLKDIV
103 0x00001C4BUL // CAN_BTR
104};
105
110static int lpc11crom_can_init(devtab_t *dev)
111{
112 /* Initialize the CAN controller */
113 (*rom)->pCAND->init_can((uint32_t*) &ClkInitTable250[0], 1);
114 /* Configure the CAN callback functions */
115 (*rom)->pCAND->config_calb((CAN_CALLBACKS*) &callbacks);
116
117 /* Enable the CAN Interrupt */
118 NVIC_EnableIRQ(CAN_IRQn);
119
120 /* Configures msgobj 1 to receive all extended frames. */
121 CAN_MSG_OBJ msg_obj;
122 msg_obj.msgobj = RX_MSG_OBJ_NUM;
123 msg_obj.mode_id = 0x000 | CAN_MSGOBJ_EXT;
124 msg_obj.mask = 0x000;
125 msg_obj.dlc = 0x000;
126 (*rom)->pCAND->config_rxmsgobj(&msg_obj);
127
128 LPC11CRomCanPriv *priv = (LPC11CRomCanPriv*)dev->priv;
129 priv->canPriv.enable = ignore_dev_function;
130 priv->canPriv.disable = ignore_dev_function;
131 priv->canPriv.tx_msg = lpc11crom_can_tx_msg;
132 return can_init(dev);
133}
134
138static void ignore_dev_function(devtab_t *dev) {}
139
140static void send_frame(struct can_frame *can_frame)
141{
142 CAN_MSG_OBJ msg_obj;
143 msg_obj.msgobj = TX_MSG_OBJ_NUM;
144 msg_obj.mode_id = can_frame->can_id |
145 (can_frame->can_rtr ? CAN_MSGOBJ_RTR : 0) |
146 (can_frame->can_eff ? CAN_MSGOBJ_EXT : 0);
147 msg_obj.mask = 0x0;
148 msg_obj.dlc = can_frame->can_dlc;
149 memcpy(msg_obj.data, can_frame->data, can_frame->can_dlc);
150 (*rom)->pCAND->can_transmit(&msg_obj);
151}
152
157static void lpc11crom_can_tx_msg(devtab_t *dev)
158{
159 LPC11CRomCanPriv *priv = (LPC11CRomCanPriv*)dev->priv;
160 if (priv->txPending) return;
161
162 struct can_frame can_frame;
163 taskENTER_CRITICAL();
164 if (os_mq_timedreceive(priv->canPriv.txQ, &can_frame, 0) != OS_MQ_NONE)
165 {
166 return;
167 }
168 priv->txPending = 1;
169 send_frame(&can_frame);
170 taskEXIT_CRITICAL();
171}
172
176void CAN_rx(uint8_t msg_obj_num)
177{
178 CAN_MSG_OBJ msg_obj;
179 /* Determine which CAN message has been received */
180 msg_obj.msgobj = msg_obj_num;
181
182 /* Now load up the msg_obj structure with the CAN message */
183 (*rom)->pCAND->can_receive(&msg_obj);
184
185 struct can_frame can_frame;
186 can_frame.can_id = msg_obj.mode_id & ((1<<30) - 1);
187 can_frame.can_rtr = (msg_obj.mode_id & CAN_MSGOBJ_RTR) ? 1 : 0;
188 can_frame.can_eff = (msg_obj.mode_id & CAN_MSGOBJ_EXT) ? 1 : 0;
189 can_frame.can_err = 0;
190 can_frame.can_dlc = msg_obj.dlc;
191 memcpy(can_frame.data, msg_obj.data, msg_obj.dlc);
192 int woken = 0;
193 if (os_mq_send_from_isr(can_private[0].canPriv.rxQ, &can_frame, &woken)
194 == OS_MQ_FULL)
195 {
196 can_private[0].canPriv.overrunCount++;
197 }
198 if (woken)
199 {
200 portYIELD();
201 }
202}
203
207void CAN_tx(uint8_t msg_obj_num){
208 // If we don't know the msg object number, let's not do anything.
209 if (msg_obj_num != TX_MSG_OBJ_NUM) return;
210 struct can_frame can_frame;
211 int woken = 0;
212 if (os_mq_receive_from_isr(can_private[0].canPriv.txQ, &can_frame, &woken)
213 != OS_MQ_NONE)
214 {
215 can_private[0].txPending = 0;
216 return;
217 }
218 send_frame(&can_frame);
219
220 if (woken)
221 {
222 portYIELD();
223 }
224}
225
229void CAN_error(uint32_t error_info)
230{
231 return;
232}
233
235static CAN_DEVTAB_ENTRY(can0, "/dev/can0", lpc11crom_can_init, &can_private[0]);
236
237#else
238#error You need to define TARGET_LPC11Cxx if you want to compiple its rom driver.
239#endif
MbedCanDriver can0(MbedCanDriver::CAN2, "/dev/can0", config_nmranet_can_bitrate())
The TCH baseboard for the mbed has CAN1 and CAN2 mixed up.
#define OS_MQ_FULL
error code for queue being full
Definition os.h:214
OS_INLINE int os_mq_send_from_isr(os_mq_t queue, const void *data, int *woken)
Send of a message to a queue from ISR context.
Definition os.h:923
OS_INLINE int os_mq_timedreceive(os_mq_t queue, void *data, long long timeout)
Receive a message from a queue.
Definition os.h:902
OS_INLINE int os_mq_receive_from_isr(os_mq_t queue, void *data, int *woken)
Receive a message from a queue from ISR context.
Definition os.h:959
#define OS_MQ_NONE
error code for no error for message queues
Definition os.h:211
All API functions of the ROM can driver.
void(* isr)(void)
Call this from the interrupt service routine.
Specifies the callbacks from the CAN stack to the application.
CAN message object.
Device tab structure.
Definition devtab.h:67
void * priv
device private data
Definition devtab.h:71