33 #if defined(PIOS_INCLUDE_CAN)
38 static void PIOS_CAN_RegisterRxCallback(uintptr_t can_id,
pios_com_callback rx_in_cb, uintptr_t context);
39 static void PIOS_CAN_RegisterTxCallback(uintptr_t can_id,
pios_com_callback tx_out_cb, uintptr_t context);
40 static void PIOS_CAN_TxStart(uintptr_t can_id, uint16_t tx_bytes_avail);
41 static void PIOS_CAN_RxStart(uintptr_t can_id, uint16_t rx_bytes_avail);
45 .rx_start = PIOS_CAN_RxStart,
46 .bind_tx_cb = PIOS_CAN_RegisterTxCallback,
47 .bind_rx_cb = PIOS_CAN_RegisterRxCallback,
50 enum pios_can_dev_magic {
51 PIOS_CAN_DEV_MAGIC = 0x41fa834A,
56 enum pios_can_dev_magic
magic;
59 uintptr_t rx_in_context;
61 uintptr_t tx_out_context;
65 #define CAN_COM_ID 0x11
66 #define MAX_SEND_LEN 8
69 static void PIOS_CAN_RxGeneric(
void);
70 static void PIOS_CAN_TxGeneric(
void);
72 static bool PIOS_CAN_validate(
struct pios_can_dev *can_dev)
74 return (can_dev->magic == PIOS_CAN_DEV_MAGIC);
77 static struct pios_can_dev *PIOS_CAN_alloc(
void)
79 struct pios_can_dev *can_dev;
81 can_dev = (
struct pios_can_dev *)
PIOS_malloc(
sizeof(*can_dev));
82 if (!can_dev)
return(NULL);
84 memset(can_dev, 0,
sizeof(*can_dev));
85 can_dev->magic = PIOS_CAN_DEV_MAGIC;
91 static struct pios_can_dev *can_dev;
104 can_dev = (
struct pios_can_dev *) PIOS_CAN_alloc();
105 if (!can_dev)
goto out_fail;
111 if (can_dev->cfg->regs == CAN1) {
112 RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
114 RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
115 RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN2, ENABLE);
119 if (can_dev->cfg->remap) {
120 if (can_dev->cfg->rx.gpio != 0)
121 GPIO_PinAFConfig(can_dev->cfg->rx.gpio,
122 can_dev->cfg->rx.pin_source,
123 can_dev->cfg->remap);
124 if (can_dev->cfg->tx.gpio != 0)
125 GPIO_PinAFConfig(can_dev->cfg->tx.gpio,
126 can_dev->cfg->tx.pin_source,
127 can_dev->cfg->remap);
131 if (can_dev->cfg->rx.gpio != 0)
132 GPIO_Init(can_dev->cfg->rx.gpio, (GPIO_InitTypeDef *)&can_dev->cfg->rx.init);
133 if (can_dev->cfg->tx.gpio != 0)
134 GPIO_Init(can_dev->cfg->tx.gpio, (GPIO_InitTypeDef *)&can_dev->cfg->tx.init);
136 *can_id = (uintptr_t)can_dev;
138 CAN_DeInit(can_dev->cfg->regs);
139 CAN_Init(can_dev->cfg->regs, (CAN_InitTypeDef *)&can_dev->cfg->init);
142 CAN_FilterInitTypeDef CAN_FilterInitStructure;
143 CAN_FilterInitStructure.CAN_FilterNumber = 0;
144 CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
145 CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
146 CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
147 CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
148 CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
149 CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
150 CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 1;
152 CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
153 CAN_FilterInit(&CAN_FilterInitStructure);
156 NVIC_Init((NVIC_InitTypeDef*) &can_dev->cfg->rx_irq.init);
157 NVIC_Init((NVIC_InitTypeDef*) &can_dev->cfg->tx_irq.init);
165 static void PIOS_CAN_RxStart(uintptr_t can_id, uint16_t rx_bytes_avail)
167 struct pios_can_dev *can_dev = (
struct pios_can_dev *)can_id;
169 bool valid = PIOS_CAN_validate(can_dev);
172 CAN_ITConfig(can_dev->cfg->regs, CAN_IT_FMP1, ENABLE);
175 static void PIOS_CAN_TxStart(uintptr_t can_id, uint16_t tx_bytes_avail)
177 struct pios_can_dev *can_dev = (
struct pios_can_dev *)can_id;
179 bool valid = PIOS_CAN_validate(can_dev);
182 CAN_ITConfig(can_dev->cfg->regs, CAN_IT_TME, ENABLE);
184 PIOS_CAN_TxGeneric();
187 static void PIOS_CAN_RegisterRxCallback(uintptr_t can_id,
pios_com_callback rx_in_cb, uintptr_t context)
189 struct pios_can_dev *can_dev = (
struct pios_can_dev *)can_id;
191 bool valid = PIOS_CAN_validate(can_dev);
198 can_dev->rx_in_context = context;
199 can_dev->rx_in_cb = rx_in_cb;
202 static void PIOS_CAN_RegisterTxCallback(uintptr_t can_id,
pios_com_callback tx_out_cb, uintptr_t context)
204 struct pios_can_dev *can_dev = (
struct pios_can_dev *)can_id;
206 bool valid = PIOS_CAN_validate(can_dev);
213 can_dev->tx_out_context = context;
214 can_dev->tx_out_cb = tx_out_cb;
229 static bool process_received_message(CanRxMsg message)
233 for (msg_id = 0; msg_id <
PIOS_CAN_LAST && pios_can_message_stdid[msg_id] != message.StdId; msg_id++);
269 if (pios_can_queues[msg_id] != NULL)
270 return pios_can_queues[msg_id];
279 pios_can_queues[msg_id] =
queue;
288 PIOS_CAN_RxGeneric();
294 PIOS_CAN_RxGeneric();
300 PIOS_CAN_RxGeneric();
306 PIOS_CAN_RxGeneric();
314 PIOS_CAN_TxGeneric();
320 PIOS_CAN_TxGeneric();
329 static void PIOS_CAN_RxGeneric(
void)
331 CAN_ClearITPendingBit(can_dev->cfg->regs, CAN_IT_FMP1);
333 bool valid = PIOS_CAN_validate(can_dev);
337 CAN_Receive(CAN1, CAN_FIFO1, &RxMessage);
339 if (RxMessage.StdId == CAN_COM_ID) {
342 if (can_dev->rx_in_cb) {
343 (void) (can_dev->rx_in_cb)(can_dev->rx_in_context, RxMessage.Data, RxMessage.DLC, NULL, &rx_need_yield);
346 process_received_message(RxMessage);
353 static void PIOS_CAN_TxGeneric(
void)
355 CAN_ClearITPendingBit(can_dev->cfg->regs, CAN_IT_TME);
357 bool valid = PIOS_CAN_validate(can_dev);
360 bool tx_need_yield =
false;
362 if (can_dev->tx_out_cb) {
366 msg.StdId = CAN_COM_ID;
368 msg.IDE = CAN_ID_STD;
369 msg.RTR = CAN_RTR_DATA;
370 msg.DLC = (can_dev->tx_out_cb)(can_dev->tx_out_context, msg.Data, MAX_SEND_LEN, NULL, &tx_need_yield);
374 CAN_Transmit(can_dev->cfg->regs, &msg);
376 CAN_ITConfig(can_dev->cfg->regs, CAN_IT_TME, DISABLE);
404 uint32_t std_id = pios_can_message_stdid[msg_id];
408 msg.StdId = std_id & 0x7FF;
410 msg.IDE = CAN_ID_STD;
411 msg.RTR = CAN_RTR_DATA;
412 msg.DLC = (bytes > 8) ? 8 : bytes;
413 memcpy(msg.Data, data, msg.DLC);
414 CAN_Transmit(can_dev->cfg->regs, &msg);
struct pios_queue * PIOS_Queue_Create(size_t queue_length, size_t item_size)
Main PiOS header to include all the compiled in PiOS options.
bool PIOS_Queue_Send_FromISR(struct pios_queue *queuep, const void *itemp, bool *wokenp)
#define PIOS_DEBUG_Assert(test)
#define PIOS_IRQ_Epilogue()
#define CAN1_TX_IRQHandler
void * PIOS_malloc(size_t size)
PiOS CAN interface header.
pios_can_messages
The set of CAN messages.
uint8_t data[XFER_BYTES_PER_PACKET]
#define CAN2_RX0_IRQHandler
static struct flyingpicmd_cfg_fa cfg
#define CAN1_RX1_IRQHandler
#define CAN1_RX0_IRQHandler
int32_t PIOS_CAN_TxData(uintptr_t id, enum pios_can_messages, uint8_t *data)
Transmit a data message with a particular message ID.
int32_t PIOS_CAN_Init(uintptr_t *id, const struct pios_can_cfg *cfg)
struct pios_queue * PIOS_CAN_RegisterMessageQueue(uintptr_t id, enum pios_can_messages msg_id)
Get a queue to receive messages of a particular message ID.
const struct pios_com_driver pios_can_com_driver
Message to tell gimbal the desired setpoint and FC state.
#define PIOS_IRQ_Prologue()
static struct pios_queue * queue
#define CAN2_TX_IRQHandler
#define CAN2_RX1_IRQHandler
#define PIOS_Assert(test)
void(* tx_start)(uintptr_t id, uint16_t tx_bytes_avail)
uint16_t(* pios_com_callback)(uintptr_t context, uint8_t *buf, uint16_t buf_len, uint16_t *headroom, bool *task_woken)