ARMEBS4  revision-26.06.2015
bus.c
Go to the documentation of this file.
1 /**
2  * \file heivs/bus.c
3  * \see heivs/bus.h
4  */
5 
6 #include "heivs/bus.h"
7 
8 #if !USE_FREERTOS
9  static void _mutex_init(const struct heivs_bus_t *bus)
10  {
11  (void)bus;
12  }
13 
14  static void _mutex_get(const struct heivs_bus_t *bus)
15  {
16  (void)bus;
17  }
18 
19  static void _mutex_put(const struct heivs_bus_t *bus)
20  {
21  (void)bus;
22  }
23 #else
24 
25  #if !INCLUDE_vTaskSuspend
26  #error INCLUDE_vTaskSuspend is necessary for bus mutexes
27  #endif
28 
29  static void _mutex_init(const struct heivs_bus_t *bus)
30  {
31  if (!bus->var->mutex_ignore && bus->var->mutex == NULL)
32  {
33  bus->var->mutex = xSemaphoreCreateMutexNamed(bus->name);
34  }
35  }
36 
37  static void _mutex_get(const struct heivs_bus_t *bus)
38  {
39  if (bus->var->mutex == NULL)
40  {
41  _mutex_init(bus);
42  }
43 
44  if (bus->var->mutex && !bus->var->mutex_ignore)
45  {
46  xSemaphoreTake(bus->var->mutex, portMAX_DELAY);
47  }
48  }
49 
50  static void _mutex_put(const struct heivs_bus_t *bus)
51  {
52  if (bus->var->mutex && !bus->var->mutex_ignore)
53  {
54  xSemaphoreGive(bus->var->mutex);
55  }
56  }
57 #endif
58 
59 status_e bus_init(const struct heivs_bus_t *bus)
60 {
61  status_e status;
62 
63  _mutex_init(bus);
64 
65  _mutex_get(bus);
66 
67  /* Bus state check */
68  if (bus->var->state == BUS_ACTIVE)
69  {
70  _mutex_put(bus);
71  return ERROR_BUS_BUSY;
72  }
73 
74  if (bus->var->state == BUS_INACTIVE)
75  {
76  _mutex_put(bus);
77  return NO_ERROR;
78  }
79 
80  bus->var->state = BUS_INACTIVE;
81 
82  /* Now do it for real */
83  status = bus->_init(bus);
84  if (status != NO_ERROR)
85  {
86  bus->var->state = BUS_NOINIT;
87  _mutex_put(bus);
88  return status;
89  }
90 
91  _mutex_put(bus);
92  return status;
93 }
94 
95 static status_e _verify_state(const struct heivs_bus_t *bus, enum heivs_bus_state_t required_state)
96 {
97  if (!BUS_PARANOIA)
98  {
99  return NO_ERROR;
100  }
101 
102  if (bus->var->state == required_state)
103  {
104  return NO_ERROR;
105  }
106 
107  switch (bus->var->state)
108  {
109  case BUS_INACTIVE:
110  bus_release(bus);
111  return ERROR_BUS_INACTIVE;
112  break;
113  case BUS_SUSPENDED:
114  bus_release(bus);
115  return ERROR_BUS_SUSPENDED;
116  break;
117  case BUS_NOINIT:
118  bus_release(bus);
119  return ERROR_BUS_NOINIT;
120  break;
121  case BUS_ACTIVE:
122  bus_release(bus);
123  return ERROR_BUS_BAD_STATE;
124  break;
125  default:
126  bus_release(bus);
127  return ERROR_BAD_SWITCH;
128  break;
129  }
130 
131  return ERROR_NOT_YET_IMPLEMENTED;
132 }
133 
134 status_e bus_get(const struct heivs_bus_t *bus)
135 {
136  _mutex_get(bus);
137 
138  /* Bus state check */
139  if (bus->var->state != BUS_INACTIVE)
140  {
141  return ERROR_BUS_BAD_STATE;
142  }
143 
144  bus->var->state = BUS_ACTIVE;
145 
146  return NO_ERROR;
147 }
148 
149 status_e bus_release(const struct heivs_bus_t *bus)
150 {
151  /* Bus state check */
152  if (bus->var->state != BUS_ACTIVE)
153  {
154  return ERROR_BUS_BAD_STATE;
155  }
156 
157  bus->var->state = BUS_INACTIVE;
158 
159  _mutex_put(bus);
160  return NO_ERROR;
161 }
162 
163 status_e bus_suspend(const struct heivs_bus_t *bus)
164 {
165  status_e status;
166 
167  /* Bus state check */
168  status = bus->_suspend(bus);
169  if (status != NO_ERROR)
170  {
171  bus_release(bus);
172  return status;
173  }
174 
175  bus->var->state = BUS_SUSPENDED;
176 
177  return status;
178 }
179 
180 status_e bus_resume(const struct heivs_bus_t *bus)
181 {
182  status_e status;
183 
184  /* Bus state check */
185  status = bus->_resume(bus);
186  if (status != NO_ERROR)
187  {
188  bus_release(bus);
189  return status;
190  }
191 
192  bus->var->state = BUS_ACTIVE;
193 
194  return status;
195 }
196 
197 
198 status_e bus_read(const struct heivs_bus_t *bus, uint32_t address, void *data, size_t len, size_t *rlen)
199 {
200  status_e status;
201 
202  // A holder for the return len if the caller don't care
203  size_t dont_care;
204 
205  if (!rlen)
206  {
207  rlen = &dont_care;
208  }
209  *rlen = 0;
210 
211  /* NO transfer, fine */
212  if (!len)
213  {
214  return NO_ERROR;
215  }
216 
217  /* No data buffer, that's bad */
218  if (!data)
219  {
220  bus_release(bus);
221  return ERROR_BAD_PARAM;
222  }
223 
224  /* Bus state check */
225  status = _verify_state(bus, BUS_ACTIVE);
226  if (status != NO_ERROR)
227  {
228  bus_release(bus);
229  return status;
230  }
231 
232  /* Now do it for real */
233  status = bus->_read(bus, address, data, len, rlen);
234  if (status != NO_ERROR)
235  {
236  bus_release(bus);
237  return status;
238  }
239 
240  return status;
241 }
242 
243 status_e bus_write(const struct heivs_bus_t *bus, uint32_t address, const void *data, size_t len)
244 {
245  status_e status;
246 
247  /* NO transfer, fine */
248  if (!len)
249  {
250  return NO_ERROR;
251  }
252 
253  /* No buffers, that's bad */
254  if (!data)
255  {
256  bus_release(bus);
257  return ERROR_BAD_PARAM;
258  }
259 
260  /* Bus state check */
261  status = _verify_state(bus, BUS_ACTIVE);
262  if (status != NO_ERROR)
263  {
264  bus_release(bus);
265  return status;
266  }
267 
268  /* Now do it for real */
269  status = bus->_write(bus, address, data, len);
270  if (status != NO_ERROR)
271  {
272  bus_release(bus);
273  return status;
274  }
275 
276  return status;
277 }
278 
279 status_e bus_writeread(const struct heivs_bus_t *bus, uint32_t address, const void *src, size_t src_len, void *dst, size_t dst_len, size_t *rlen)
280 {
281  status_e status;
282 
283  // A holder for the return len if the caller don't care
284  size_t dont_care;
285 
286  if (!rlen)
287  {
288  rlen = &dont_care;
289  }
290  *rlen = 0;
291 
292  /* NO transfer, fine */
293  if (!src_len && !dst_len)
294  {
295  return NO_ERROR;
296  }
297 
298  /* TX only */
299  if (!dst_len)
300  {
301  return bus_write(bus, address, src, src_len);
302  }
303 
304  /* RX only */
305  if (!src_len)
306  {
307  return bus_read(bus, address, dst, dst_len, rlen);
308  }
309 
310  /* No data buffer, that's bad */
311  if (!src || !dst)
312  {
313  bus_release(bus);
314  return ERROR_BAD_PARAM;
315  }
316 
317  /* Bus state check */
318  status = _verify_state(bus, BUS_ACTIVE);
319  if (status != NO_ERROR)
320  {
321  bus_release(bus);
322  return status;
323  }
324 
325  /* Now do it for real */
326  status = bus->_writeread(bus, address, src, src_len, dst, dst_len, rlen);
327  if (status != NO_ERROR)
328  {
329  bus_release(bus);
330  return status;
331  }
332 
333  return status;
334 }
335 
bus abstraction
Bus not operable while in power down.
Definition: error.h:80
Bus handler.
Definition: bus.h:92
const char * name
Definition: bus.h:102
status_e(* _suspend)(const struct heivs_bus_t *)
Definition: bus.h:117
Have you called bus_get ?
Definition: error.h:79
status_e bus_release(const struct heivs_bus_t *bus)
Release exclusive access to the bus.
Definition: bus.c:149
Have you called bus_init ?
Definition: error.h:78
status_e bus_resume(const struct heivs_bus_t *bus)
Resume the bus (from low power mode)
Definition: bus.c:180
struct heivs_bus_var_t * var
Definition: bus.h:97
status_e(* _init)(const struct heivs_bus_t *)
Definition: bus.h:112
see bus_get/bus_release and errors
Definition: error.h:81
status_e bus_write(const struct heivs_bus_t *bus, uint32_t address, const void *data, size_t len)
Write data to the bus.
Definition: bus.c:243
Parameter unsupported.
Definition: error.h:56
#define BUS_PARANOIA
Definition: bus.h:31
Impossible switch value.
Definition: error.h:63
status_e(* _read)(const struct heivs_bus_t *, uint32_t address, uint8_t *data, size_t len, size_t *rlen)
Definition: bus.h:132
status_e bus_init(const struct heivs_bus_t *bus)
initialize the bus
Definition: bus.c:59
status_e(* _resume)(const struct heivs_bus_t *)
Definition: bus.h:122
status_e bus_read(const struct heivs_bus_t *bus, uint32_t address, void *data, size_t len, size_t *rlen)
Resume the bus (from low power mode)
Definition: bus.c:198
status_e bus_get(const struct heivs_bus_t *bus)
Get exclusive access to the bus.
Definition: bus.c:134
Definition: bus.h:61
heivs_bus_state_t
State of the bus.
Definition: bus.h:36
status_e
Known errors.
Definition: error.h:21
status_e bus_writeread(const struct heivs_bus_t *bus, uint32_t address, const void *src, size_t src_len, void *dst, size_t dst_len, size_t *rlen)
Combined write and read data.
Definition: bus.c:279
No error.
Definition: error.h:28
status_e bus_suspend(const struct heivs_bus_t *bus)
Suspend the bus (low power mode)
Definition: bus.c:163
Definition: bus.h:45