34 #if defined(PIOS_INCLUDE_CAN)
39 static void PIOS_CAN_RegisterRxCallback(uintptr_t can_id,
pios_com_callback rx_in_cb, uintptr_t context);
40 static void PIOS_CAN_RegisterTxCallback(uintptr_t can_id,
pios_com_callback tx_out_cb, uintptr_t context);
41 static void PIOS_CAN_TxStart(uintptr_t can_id, uint16_t tx_bytes_avail);
42 static void PIOS_CAN_RxStart(uintptr_t can_id, uint16_t rx_bytes_avail);
46 .rx_start = PIOS_CAN_RxStart,
47 .bind_tx_cb = PIOS_CAN_RegisterTxCallback,
48 .bind_rx_cb = PIOS_CAN_RegisterRxCallback,
51 enum pios_can_dev_magic {
52 PIOS_CAN_DEV_MAGIC = 0x41fa834A,
57 enum pios_can_dev_magic
magic;
60 uintptr_t rx_in_context;
62 uintptr_t tx_out_context;
66 #define CAN_COM_ID 0x11
67 #define MAX_SEND_LEN 8
71 static bool PIOS_CAN_validate(
struct pios_can_dev *can_dev)
73 return (can_dev->magic == PIOS_CAN_DEV_MAGIC);
76 static struct pios_can_dev *PIOS_CAN_alloc(
void)
78 struct pios_can_dev *can_dev;
80 can_dev = (
struct pios_can_dev *)
PIOS_malloc(
sizeof(*can_dev));
81 if (!can_dev)
return(NULL);
83 memset(can_dev, 0,
sizeof(*can_dev));
84 can_dev->magic = PIOS_CAN_DEV_MAGIC;
90 static struct pios_can_dev *can_dev;
103 can_dev = (
struct pios_can_dev *) PIOS_CAN_alloc();
104 if (!can_dev)
goto out_fail;
110 RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);
113 if (can_dev->cfg->remap) {
114 if (can_dev->cfg->rx.gpio != 0)
115 GPIO_PinAFConfig(can_dev->cfg->rx.gpio,
116 can_dev->cfg->rx.pin_source,
117 can_dev->cfg->remap);
118 if (can_dev->cfg->tx.gpio != 0)
119 GPIO_PinAFConfig(can_dev->cfg->tx.gpio,
120 can_dev->cfg->tx.pin_source,
121 can_dev->cfg->remap);
125 if (can_dev->cfg->rx.gpio != 0)
126 GPIO_Init(can_dev->cfg->rx.gpio, (GPIO_InitTypeDef *)&can_dev->cfg->rx.init);
127 if (can_dev->cfg->tx.gpio != 0)
128 GPIO_Init(can_dev->cfg->tx.gpio, (GPIO_InitTypeDef *)&can_dev->cfg->tx.init);
130 *can_id = (uintptr_t)can_dev;
132 CAN_DeInit(can_dev->cfg->regs);
133 CAN_Init(can_dev->cfg->regs, (CAN_InitTypeDef *)&can_dev->cfg->init);
136 CAN_FilterInitTypeDef CAN_FilterInitStructure;
137 CAN_FilterInitStructure.CAN_FilterNumber = 0;
138 CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
139 CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
140 CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
141 CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
142 CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
143 CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
144 CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 1;
146 CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;
147 CAN_FilterInit(&CAN_FilterInitStructure);
150 NVIC_Init((NVIC_InitTypeDef*) &can_dev->cfg->rx_irq.init);
151 NVIC_Init((NVIC_InitTypeDef*) &can_dev->cfg->tx_irq.init);
159 static void PIOS_CAN_RxStart(uintptr_t can_id, uint16_t rx_bytes_avail)
161 struct pios_can_dev *can_dev = (
struct pios_can_dev *)can_id;
163 bool valid = PIOS_CAN_validate(can_dev);
166 CAN_ITConfig(can_dev->cfg->regs, CAN_IT_FMP1, ENABLE);
169 static void PIOS_CAN_TxStart(uintptr_t can_id, uint16_t tx_bytes_avail)
171 struct pios_can_dev *can_dev = (
struct pios_can_dev *)can_id;
173 bool valid = PIOS_CAN_validate(can_dev);
176 CAN_ITConfig(can_dev->cfg->regs, CAN_IT_TME, ENABLE);
181 static void PIOS_CAN_RegisterRxCallback(uintptr_t can_id,
pios_com_callback rx_in_cb, uintptr_t context)
183 struct pios_can_dev *can_dev = (
struct pios_can_dev *)can_id;
185 bool valid = PIOS_CAN_validate(can_dev);
192 can_dev->rx_in_context = context;
193 can_dev->rx_in_cb = rx_in_cb;
196 static void PIOS_CAN_RegisterTxCallback(uintptr_t can_id,
pios_com_callback tx_out_cb, uintptr_t context)
198 struct pios_can_dev *can_dev = (
struct pios_can_dev *)can_id;
200 bool valid = PIOS_CAN_validate(can_dev);
207 can_dev->tx_out_context = context;
208 can_dev->tx_out_cb = tx_out_cb;
223 static bool process_received_message(CanRxMsg message)
227 for (msg_id = 0; msg_id <
PIOS_CAN_LAST && pios_can_message_stdid[msg_id] != message.StdId; msg_id++);
263 if (pios_can_queues[msg_id] != NULL)
264 return pios_can_queues[msg_id];
273 pios_can_queues[msg_id] =
queue;
280 static void PIOS_CAN_RxGeneric(
void);
281 static void PIOS_CAN_TxGeneric(
void);
286 PIOS_CAN_RxGeneric();
293 PIOS_CAN_TxGeneric();
302 static void PIOS_CAN_RxGeneric(
void)
304 CAN_ClearITPendingBit(can_dev->cfg->regs, CAN_IT_FMP1);
306 bool valid = PIOS_CAN_validate(can_dev);
310 CAN_Receive(CAN1, CAN_FIFO1, &RxMessage);
312 bool rx_need_yield =
false;
313 if (RxMessage.StdId == CAN_COM_ID) {
314 if (can_dev->rx_in_cb) {
315 (void) (can_dev->rx_in_cb)(can_dev->rx_in_context, RxMessage.Data, RxMessage.DLC, NULL, &rx_need_yield);
318 rx_need_yield = process_received_message(RxMessage);
325 static void PIOS_CAN_TxGeneric(
void)
327 CAN_ClearITPendingBit(can_dev->cfg->regs, CAN_IT_TME);
329 bool valid = PIOS_CAN_validate(can_dev);
332 bool tx_need_yield =
false;
334 if (can_dev->tx_out_cb) {
338 msg.StdId = CAN_COM_ID;
340 msg.IDE = CAN_ID_STD;
341 msg.RTR = CAN_RTR_DATA;
342 msg.DLC = (can_dev->tx_out_cb)(can_dev->tx_out_context, msg.Data, MAX_SEND_LEN, NULL, &tx_need_yield);
346 CAN_Transmit(can_dev->cfg->regs, &msg);
348 CAN_ITConfig(can_dev->cfg->regs, CAN_IT_TME, DISABLE);
376 uint32_t std_id = pios_can_message_stdid[msg_id];
380 msg.StdId = std_id & 0x7FF;
382 msg.IDE = CAN_ID_STD;
383 msg.RTR = CAN_RTR_DATA;
384 msg.DLC = (bytes > 8) ? 8 : bytes;
385 memcpy(msg.Data, data, msg.DLC);
386 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()
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]
static struct flyingpicmd_cfg_fa cfg
#define CAN1_RX1_IRQHandler
#define USB_HP_CAN1_TX_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 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)