]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lib.git/blob - rpp/src/drv/spi.c
Make the RPP layer thread safe
[pes-rpp/rpp-lib.git] / rpp / src / drv / spi.c
1 /* Copyright (C) 2012-2013, 2015 Czech Technical University in Prague
2  *
3  * This document contains proprietary information belonging to Czech
4  * Technical University in Prague. Passing on and copying of this
5  * document, and communication of its contents is not permitted
6  * without prior written authorization.
7  *
8  * File : spi.c
9  */
10
11 //#include "ul/ul_list.h"
12 //#include "drv/spi.h"
13 //#include "cpu_def.h"
14 //#include "ul/ul_list.h"
15 #include "drv/spi.h"
16
17 int spi_msg_rq_ins(spi_drv_t *ifc, spi_msg_head_t *msg)
18 {
19         spi_isr_lock_level_t saveif;
20
21         if (!ifc)
22                 return -1;
23
24         if (!(ifc->flags & SPI_IFC_ON))
25                 return -1;
26
27         spi_isr_lock(saveif);
28         spi_rq_queue_insert(ifc, msg);
29         spi_isr_unlock(saveif);
30         ifc->ctrl_fnc(ifc, SPI_CTRL_WAKE_RQ, NULL);
31         return 0;
32 }
33
34 int spi_transfer_callback(struct spi_drv *ifc, int code, struct spi_msg_head *msg)
35 {
36         if (msg->private)
37                 msg->private = 0;
38         return 0;
39 }
40
41 /*
42  * This function is thread safe.
43  */
44 int spi_transfer(spi_drv_t *ifc, int addr, int rq_len, const void *tx_buf, void *rx_buf)
45 {
46         spi_msg_head_t msg;
47
48         msg.flags = 0;
49         //msg.ifc = NULL;
50         spi_rq_queue_init_detached(&msg);
51         msg.addr = addr;
52         msg.rq_len = rq_len;
53         msg.tx_buf = tx_buf;
54         msg.rx_buf = rx_buf;
55         msg.callback = spi_transfer_callback;
56         msg.private = 1;
57
58         if (spi_msg_rq_ins(ifc, &msg) < 0)
59                 return -1;
60
61         /* Wait for the request completion */
62         while (msg.private)
63                 __memory_barrier();
64
65
66         if (msg.flags & (SPI_MSG_FAIL | SPI_MSG_ABORT))
67                 return -1;
68
69         return msg.rq_len;
70 }
71
72 #define MIN(a,b) ((a) < (b) ? (a) : (b))
73
74 int8_t port_spi_set(const struct port_desc *port, void *values, size_t size)
75 {
76         spi_drv_t *ifc;
77         uint8_t rx[4];
78
79         assert(port->numchn == 1);
80         assert(size == port->bpch/8);
81         assert(size <= sizeof(rx));
82
83         ifc = spi_find_drv(NULL, port->cfg.spi.ifc);
84         if (ifc == NULL)
85                 return FAILURE;
86
87         if (!(ifc->flags & SPI_IFC_ON))
88                 return FAILURE;
89
90         spi_transfer(ifc, port->cfg.spi.cs, size, values, rx);
91
92         memcpy(values, rx, MIN(size, port->numchn * port->bpch/8));
93         return SUCCESS;
94 }