dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pios_com_msg.c
Go to the documentation of this file.
1 
15 /*
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 3 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful, but
22  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
23  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24  * for more details.
25  *
26  * You should have received a copy of the GNU General Public License along
27  * with this program; if not, see <http://www.gnu.org/licenses/>
28  */
29 
30 /* Project Includes */
31 #include "pios.h"
32 
33 #if defined(PIOS_INCLUDE_COM_MSG)
34 
35 #include "pios_com.h"
36 
37 #define PIOS_COM_MSG_MAX_LEN 63
38 
39 struct pios_com_msg_dev {
40  uintptr_t lower_id;
41  const struct pios_com_driver * driver;
42 
43  uint8_t rx_msg_buffer[PIOS_COM_MSG_MAX_LEN];
44  volatile bool rx_msg_full;
45 
46  uint8_t tx_msg_buffer[PIOS_COM_MSG_MAX_LEN];
47  volatile bool tx_msg_full;
48 };
49 
50 static struct pios_com_msg_dev com_msg_dev;
51 
52 static uint16_t PIOS_COM_MSG_TxOutCallback(uintptr_t context, uint8_t * buf, uint16_t buf_len, uint16_t * headroom, bool * need_yield);
53 static uint16_t PIOS_COM_MSG_RxInCallback(uintptr_t context, uint8_t * buf, uint16_t buf_len, uint16_t * headroom, bool * need_yield);
54 
55 int32_t PIOS_COM_MSG_Init(uintptr_t * com_id, const struct pios_com_driver * driver, uintptr_t lower_id)
56 {
57  PIOS_Assert(com_id);
58  PIOS_Assert(driver);
59 
60  PIOS_Assert(driver->bind_tx_cb);
61  PIOS_Assert(driver->bind_rx_cb);
62 
63  struct pios_com_msg_dev * com_dev = &com_msg_dev;
64 
65  com_dev->driver = driver;
66  com_dev->lower_id = lower_id;
67 
68  com_dev->rx_msg_full = false;
69  (com_dev->driver->bind_rx_cb)(lower_id, PIOS_COM_MSG_RxInCallback, (uintptr_t)com_dev);
70  (com_dev->driver->rx_start)(com_dev->lower_id, sizeof(com_dev->rx_msg_buffer));
71 
72  com_dev->tx_msg_full = false;
73  (com_dev->driver->bind_tx_cb)(lower_id, PIOS_COM_MSG_TxOutCallback, (uintptr_t)com_dev);
74 
75  *com_id = (uintptr_t)com_dev;
76  return(0);
77 }
78 
79 static uint16_t PIOS_COM_MSG_TxOutCallback(uintptr_t context, uint8_t * buf, uint16_t buf_len, uint16_t * headroom, bool * need_yield)
80 {
81  struct pios_com_msg_dev * com_dev = (struct pios_com_msg_dev *)context;
82 
83  PIOS_Assert(buf);
84  PIOS_Assert(buf_len);
85 
86  uint16_t bytes_from_fifo = 0;
87 
88  if (com_dev->tx_msg_full && (buf_len >= sizeof(com_dev->tx_msg_buffer))) {
89  /* Room for an entire message, send it */
90  memcpy(buf, com_dev->tx_msg_buffer, sizeof(com_dev->tx_msg_buffer));
91  bytes_from_fifo = sizeof(com_dev->tx_msg_buffer);
92  com_dev->tx_msg_full = false;
93  }
94 
95  if (headroom) {
96  if (com_dev->tx_msg_full) {
97  *headroom = sizeof(com_dev->tx_msg_buffer);
98  } else {
99  *headroom = 0;
100  }
101  }
102 
103  return (bytes_from_fifo);
104 }
105 
106 static uint16_t PIOS_COM_MSG_RxInCallback(uintptr_t context, uint8_t * buf, uint16_t buf_len, uint16_t * headroom, bool * need_yield)
107 {
108  struct pios_com_msg_dev * com_dev = (struct pios_com_msg_dev *)context;
109 
110  uint16_t bytes_into_fifo = 0;
111 
112  if (!com_dev->rx_msg_full && (buf_len >= sizeof(com_dev->rx_msg_buffer))) {
113  memcpy(com_dev->rx_msg_buffer, buf, sizeof(com_dev->rx_msg_buffer));
114  bytes_into_fifo = sizeof(com_dev->rx_msg_buffer);
115  com_dev->rx_msg_full = true;
116  }
117 
118  if (headroom) {
119  if (!com_dev->rx_msg_full) {
120  *headroom = sizeof(com_dev->rx_msg_buffer);
121  } else {
122  *headroom = 0;
123  }
124  }
125 
126  return (bytes_into_fifo);
127 }
128 
129 int32_t PIOS_COM_MSG_Send(uintptr_t com_id, const uint8_t *msg, uint16_t msg_len)
130 {
131  PIOS_Assert(msg);
132  PIOS_Assert(msg_len);
133 
134  struct pios_com_msg_dev * com_dev = (struct pios_com_msg_dev *)com_id;
135 
136  PIOS_Assert(msg_len == sizeof(com_dev->tx_msg_buffer));
137 
138  /* Wait forever for room in the tx buffer */
139  while (com_dev->tx_msg_full) {
140  /* Kick the transmitter while we wait */
141  if (com_dev->driver->tx_start) {
142  (com_dev->driver->tx_start)(com_dev->lower_id, sizeof(com_dev->tx_msg_buffer));
143  }
144  }
145 
146  memcpy((void *) com_dev->tx_msg_buffer, msg, msg_len);
147  com_dev->tx_msg_full = true;
148 
149  /* Kick the transmitter now that we've queued our message */
150  if (com_dev->driver->tx_start) {
151  (com_dev->driver->tx_start)(com_dev->lower_id, sizeof(com_dev->tx_msg_buffer));
152  }
153 
154  return 0;
155 }
156 
157 uint16_t PIOS_COM_MSG_Receive(uintptr_t com_id, uint8_t * msg, uint16_t msg_len)
158 {
159  PIOS_Assert(msg);
160  PIOS_Assert(msg_len);
161 
162  struct pios_com_msg_dev * com_dev = (struct pios_com_msg_dev *)com_id;
163 
164  PIOS_Assert(msg_len == sizeof(com_dev->rx_msg_buffer));
165 
166  if (!com_dev->rx_msg_full) {
167  /* There's room in our buffer, kick the receiver */
168  (com_dev->driver->rx_start)(com_dev->lower_id, sizeof(com_dev->rx_msg_buffer));
169  } else {
170  memcpy(msg, com_dev->rx_msg_buffer, msg_len);
171  com_dev->rx_msg_full = false;
172 
173  return msg_len;
174  }
175 
176  return 0;
177 }
178 
179 #endif /* PIOS_INCLUDE_COM_MSG */
180 
uint16_t PIOS_COM_MSG_Receive(uintptr_t com_id, uint8_t *buf, uint16_t buf_len)
int32_t PIOS_COM_MSG_Send(uintptr_t com_id, const uint8_t *msg, uint16_t msg_len)
Main PiOS header to include all the compiled in PiOS options.
void(* bind_tx_cb)(uintptr_t id, pios_com_callback tx_out_cb, uintptr_t context)
Definition: pios_com.h:48
COM layer functions header.
int32_t PIOS_COM_MSG_Init(uintptr_t *com_id, const struct pios_com_driver *driver, uintptr_t lower_id)
void(* bind_rx_cb)(uintptr_t id, pios_com_callback rx_in_cb, uintptr_t context)
Definition: pios_com.h:47
#define PIOS_Assert(test)
Definition: pios_debug.h:52