User | Revision | Line number | New contents of line |
humlet |
9:65aae53a34de
|
1
|
#include "i2cRtos_api.h"
|
humlet |
9:65aae53a34de
|
2
|
|
humlet |
9:65aae53a34de
|
3
|
#if DEVICE_I2C
|
humlet |
9:65aae53a34de
|
4
|
|
humlet |
13:530968937ccb
|
5
|
#include "us_ticker_api.h"
|
humlet |
9:65aae53a34de
|
6
|
#include "cmsis_os.h"
|
humlet |
9:65aae53a34de
|
7
|
#include "error.h"
|
humlet |
9:65aae53a34de
|
8
|
|
humlet |
13:530968937ccb
|
9
|
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
|
humlet |
9:65aae53a34de
|
10
|
#define I2C_CONSET(x) (x->i2c->I2CONSET)
|
humlet |
9:65aae53a34de
|
11
|
#define I2C_CONCLR(x) (x->i2c->I2CONCLR)
|
humlet |
9:65aae53a34de
|
12
|
#define I2C_STAT(x) (x->i2c->I2STAT)
|
humlet |
9:65aae53a34de
|
13
|
#define I2C_DAT(x) (x->i2c->I2DAT)
|
humlet |
13:530968937ccb
|
14
|
#elif defined(TARGET_LPC11U24)
|
humlet |
13:530968937ccb
|
15
|
#define I2C_CONSET(x) (x->i2c->CONSET)
|
humlet |
13:530968937ccb
|
16
|
#define I2C_CONCLR(x) (x->i2c->CONCLR)
|
humlet |
13:530968937ccb
|
17
|
#define I2C_STAT(x) (x->i2c->STAT)
|
humlet |
13:530968937ccb
|
18
|
#define I2C_DAT(x) (x->i2c->DAT)
|
humlet |
13:530968937ccb
|
19
|
#endif
|
humlet |
9:65aae53a34de
|
20
|
|
humlet |
13:530968937ccb
|
21
|
#include "gpio_api.h"
|
humlet |
13:530968937ccb
|
22
|
static gpio_t gpio[2]; // evillive
|
humlet |
10:e3d6c92ff222
|
23
|
|
humlet |
9:65aae53a34de
|
24
|
enum I2cIsrCmd {
|
humlet |
9:65aae53a34de
|
25
|
readMst,
|
humlet |
9:65aae53a34de
|
26
|
writeMst,
|
humlet |
9:65aae53a34de
|
27
|
readSlv,
|
humlet |
9:65aae53a34de
|
28
|
writeSlv,
|
humlet |
9:65aae53a34de
|
29
|
waitSI
|
humlet |
9:65aae53a34de
|
30
|
};
|
humlet |
9:65aae53a34de
|
31
|
struct I2cIsrTransfer {
|
humlet |
9:65aae53a34de
|
32
|
i2c_t* obj;
|
humlet |
9:65aae53a34de
|
33
|
enum I2cIsrCmd cmd;
|
humlet |
9:65aae53a34de
|
34
|
int len;
|
humlet |
9:65aae53a34de
|
35
|
int cnt;
|
humlet |
9:65aae53a34de
|
36
|
int stat;
|
humlet |
9:65aae53a34de
|
37
|
char* rData;
|
humlet |
9:65aae53a34de
|
38
|
const char* wData;
|
humlet |
9:65aae53a34de
|
39
|
};
|
humlet |
10:e3d6c92ff222
|
40
|
static struct I2cIsrTransfer i2c_transfer[2]; // evillive: dare to get rid of volatile?
|
humlet |
9:65aae53a34de
|
41
|
|
humlet |
9:65aae53a34de
|
42
|
|
humlet |
9:65aae53a34de
|
43
|
struct IsrIrqSem {
|
humlet |
9:65aae53a34de
|
44
|
IRQn_Type irq;
|
humlet |
9:65aae53a34de
|
45
|
osSemaphoreId sem;
|
humlet |
9:65aae53a34de
|
46
|
};
|
humlet |
9:65aae53a34de
|
47
|
static struct IsrIrqSem isrIrqSem[2];
|
humlet |
9:65aae53a34de
|
48
|
|
humlet |
9:65aae53a34de
|
49
|
|
humlet |
9:65aae53a34de
|
50
|
// little helpers cloned from official i2c api
|
humlet |
9:65aae53a34de
|
51
|
static inline void i2c_conclr(i2c_t *obj, int start, int stop, int interrupt, int acknowledge)
|
humlet |
9:65aae53a34de
|
52
|
{
|
humlet |
9:65aae53a34de
|
53
|
I2C_CONCLR(obj) = (start << 5)
|
humlet |
9:65aae53a34de
|
54
|
| (stop << 4)
|
humlet |
9:65aae53a34de
|
55
|
| (interrupt << 3)
|
humlet |
9:65aae53a34de
|
56
|
| (acknowledge << 2);
|
humlet |
9:65aae53a34de
|
57
|
}
|
humlet |
9:65aae53a34de
|
58
|
static inline void i2c_conset(i2c_t *obj, int start, int stop, int interrupt, int acknowledge)
|
humlet |
9:65aae53a34de
|
59
|
{
|
humlet |
9:65aae53a34de
|
60
|
I2C_CONSET(obj) = (start << 5)
|
humlet |
9:65aae53a34de
|
61
|
| (stop << 4)
|
humlet |
9:65aae53a34de
|
62
|
| (interrupt << 3)
|
humlet |
9:65aae53a34de
|
63
|
| (acknowledge << 2);
|
humlet |
9:65aae53a34de
|
64
|
}
|
humlet |
9:65aae53a34de
|
65
|
static inline void i2c_clear_SI(i2c_t *obj)
|
humlet |
9:65aae53a34de
|
66
|
{
|
humlet |
9:65aae53a34de
|
67
|
i2c_conclr(obj, 0, 0, 1, 0);
|
humlet |
9:65aae53a34de
|
68
|
}
|
humlet |
9:65aae53a34de
|
69
|
static inline int i2c_status(i2c_t *obj)
|
humlet |
9:65aae53a34de
|
70
|
{
|
humlet |
9:65aae53a34de
|
71
|
return I2C_STAT(obj);
|
humlet |
9:65aae53a34de
|
72
|
}
|
humlet |
9:65aae53a34de
|
73
|
|
humlet |
9:65aae53a34de
|
74
|
// ISR stuff
|
humlet |
10:e3d6c92ff222
|
75
|
static void i2cRtos_isr(uint32_t ch)
|
humlet |
9:65aae53a34de
|
76
|
{
|
humlet |
11:8c1d44595620
|
77
|
struct I2cIsrTransfer* tr=&(i2c_transfer[ch]);
|
humlet |
12:6ddadcbbdca2
|
78
|
if(tr->cmd==waitSI) {
|
humlet |
9:65aae53a34de
|
79
|
osSemaphoreRelease(isrIrqSem[ch].sem);
|
humlet |
9:65aae53a34de
|
80
|
NVIC_DisableIRQ(isrIrqSem[ch].irq);
|
humlet |
9:65aae53a34de
|
81
|
return;
|
humlet |
9:65aae53a34de
|
82
|
}
|
humlet |
9:65aae53a34de
|
83
|
int stat=i2c_status(tr->obj);
|
humlet |
9:65aae53a34de
|
84
|
int stay = 0;
|
humlet |
9:65aae53a34de
|
85
|
switch(tr->cmd) {
|
humlet |
11:8c1d44595620
|
86
|
case readMst:
|
humlet |
11:8c1d44595620
|
87
|
switch(stat) {
|
humlet |
11:8c1d44595620
|
88
|
case 0x50:
|
humlet |
11:8c1d44595620
|
89
|
(tr->rData)[tr->cnt] = (char)(I2C_DAT(tr->obj) & 0xff);
|
humlet |
11:8c1d44595620
|
90
|
case 0x40:
|
humlet |
11:8c1d44595620
|
91
|
++(tr->cnt);
|
humlet |
11:8c1d44595620
|
92
|
if(tr->cnt != tr->len-1)
|
humlet |
10:e3d6c92ff222
|
93
|
i2c_conset(tr->obj, 0, 0, 0, 1);
|
humlet |
11:8c1d44595620
|
94
|
else
|
humlet |
10:e3d6c92ff222
|
95
|
i2c_conclr(tr->obj, 0, 0, 0, 1);
|
humlet |
9:65aae53a34de
|
96
|
stay = 1;
|
humlet |
11:8c1d44595620
|
97
|
break;
|
humlet |
11:8c1d44595620
|
98
|
case 0x58:
|
humlet |
11:8c1d44595620
|
99
|
(tr->rData)[tr->cnt] = (char)(I2C_DAT(tr->obj) & 0xff);
|
humlet |
11:8c1d44595620
|
100
|
stat=0;
|
humlet |
11:8c1d44595620
|
101
|
break;
|
humlet |
9:65aae53a34de
|
102
|
}
|
humlet |
9:65aae53a34de
|
103
|
break;
|
humlet |
11:8c1d44595620
|
104
|
case writeMst:
|
humlet |
11:8c1d44595620
|
105
|
switch(stat) {
|
humlet |
11:8c1d44595620
|
106
|
case 0x18:
|
humlet |
11:8c1d44595620
|
107
|
case 0x28:
|
humlet |
11:8c1d44595620
|
108
|
if(++(tr->cnt)!=tr->len) { // evillive
|
humlet |
11:8c1d44595620
|
109
|
I2C_DAT(tr->obj) = (tr->wData)[tr->cnt];
|
humlet |
11:8c1d44595620
|
110
|
stay=1;
|
humlet |
11:8c1d44595620
|
111
|
} else {
|
humlet |
11:8c1d44595620
|
112
|
stat=0;
|
humlet |
11:8c1d44595620
|
113
|
}
|
humlet |
9:65aae53a34de
|
114
|
}
|
humlet |
9:65aae53a34de
|
115
|
break;
|
humlet |
11:8c1d44595620
|
116
|
case readSlv:
|
humlet |
11:8c1d44595620
|
117
|
++(tr->cnt);
|
humlet |
9:65aae53a34de
|
118
|
if(stat==0x80 || stat==0x90)
|
humlet |
11:8c1d44595620
|
119
|
(tr->rData)[tr->cnt] = I2C_DAT(tr->obj) & 0xFF;
|
humlet |
11:8c1d44595620
|
120
|
stay = (stat==0x80 || stat==0x90 || stat==0x060 || stat==0x70) && (tr->cnt < tr->len-1);
|
humlet |
9:65aae53a34de
|
121
|
break;
|
humlet |
11:8c1d44595620
|
122
|
case writeSlv:
|
humlet |
11:8c1d44595620
|
123
|
++(tr->cnt);
|
humlet |
11:8c1d44595620
|
124
|
stay = tr->cnt<tr->len && stat==0xb8;
|
humlet |
9:65aae53a34de
|
125
|
if(stay)
|
humlet |
11:8c1d44595620
|
126
|
I2C_DAT(tr->obj) = tr->wData[tr->cnt];
|
humlet |
9:65aae53a34de
|
127
|
break;
|
humlet |
9:65aae53a34de
|
128
|
}
|
humlet |
9:65aae53a34de
|
129
|
if(stay) {
|
humlet |
9:65aae53a34de
|
130
|
i2c_clear_SI(tr->obj);
|
humlet |
9:65aae53a34de
|
131
|
} else {
|
humlet |
9:65aae53a34de
|
132
|
tr->stat = stat;
|
humlet |
9:65aae53a34de
|
133
|
osSemaphoreRelease(isrIrqSem[ch].sem);
|
humlet |
9:65aae53a34de
|
134
|
NVIC_DisableIRQ(isrIrqSem[ch].irq);
|
humlet |
9:65aae53a34de
|
135
|
}
|
humlet |
9:65aae53a34de
|
136
|
}
|
humlet |
13:530968937ccb
|
137
|
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
|
humlet |
11:8c1d44595620
|
138
|
static void i2cRtos_isr_ch0()
|
humlet |
9:65aae53a34de
|
139
|
{
|
humlet |
11:8c1d44595620
|
140
|
//gpio_write(&gpio[0], 1);
|
humlet |
9:65aae53a34de
|
141
|
i2cRtos_isr(0);
|
humlet |
11:8c1d44595620
|
142
|
//gpio_write(&gpio[0], 0);
|
humlet |
9:65aae53a34de
|
143
|
}
|
humlet |
13:530968937ccb
|
144
|
#endif
|
humlet |
11:8c1d44595620
|
145
|
static void i2cRtos_isr_ch1()
|
humlet |
9:65aae53a34de
|
146
|
{
|
humlet |
11:8c1d44595620
|
147
|
//gpio_write(&gpio[1], 1);
|
humlet |
9:65aae53a34de
|
148
|
i2cRtos_isr(1);
|
humlet |
11:8c1d44595620
|
149
|
//gpio_write(&gpio[1], 0);
|
humlet |
9:65aae53a34de
|
150
|
}
|
humlet |
9:65aae53a34de
|
151
|
|
humlet |
9:65aae53a34de
|
152
|
|
humlet |
9:65aae53a34de
|
153
|
// determine channel
|
humlet |
11:8c1d44595620
|
154
|
static inline uint32_t i2c_get_channel(const i2c_t *obj)
|
humlet |
9:65aae53a34de
|
155
|
{
|
humlet |
9:65aae53a34de
|
156
|
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
|
humlet |
9:65aae53a34de
|
157
|
switch((I2CName)(obj->i2c)) {
|
humlet |
9:65aae53a34de
|
158
|
case I2C_1:
|
humlet |
9:65aae53a34de
|
159
|
return 0;
|
humlet |
9:65aae53a34de
|
160
|
case I2C_2:
|
humlet |
9:65aae53a34de
|
161
|
return 1;
|
humlet |
9:65aae53a34de
|
162
|
default:
|
humlet |
9:65aae53a34de
|
163
|
error("Dial911 i2c_get_channel: Invaid I2CName \n");
|
humlet |
9:65aae53a34de
|
164
|
}
|
humlet |
9:65aae53a34de
|
165
|
#endif
|
humlet |
10:e3d6c92ff222
|
166
|
return 1;
|
humlet |
9:65aae53a34de
|
167
|
}
|
humlet |
9:65aae53a34de
|
168
|
|
humlet |
9:65aae53a34de
|
169
|
|
humlet |
9:65aae53a34de
|
170
|
// wait for ISR finished
|
humlet |
12:6ddadcbbdca2
|
171
|
static inline void i2cRtos_wait_and_see(i2c_t *obj, int ch, uint32_t tmOut) //evillive
|
humlet |
9:65aae53a34de
|
172
|
{
|
humlet |
11:8c1d44595620
|
173
|
struct IsrIrqSem* iis = &(isrIrqSem[ch]);
|
humlet |
10:e3d6c92ff222
|
174
|
__disable_irq();
|
humlet |
9:65aae53a34de
|
175
|
i2c_clear_SI(obj);
|
humlet |
11:8c1d44595620
|
176
|
NVIC_ClearPendingIRQ(iis->irq);
|
humlet |
9:65aae53a34de
|
177
|
NVIC_EnableIRQ(iis->irq);
|
humlet |
10:e3d6c92ff222
|
178
|
__enable_irq();
|
humlet |
11:8c1d44595620
|
179
|
if(osSemaphoreWait(iis->sem, tmOut)!=1) NVIC_DisableIRQ(iis->irq);
|
humlet |
11:8c1d44595620
|
180
|
}
|
humlet |
11:8c1d44595620
|
181
|
|
humlet |
12:6ddadcbbdca2
|
182
|
static inline void i2cRtos_waitSI(i2c_t *obj, uint32_t tmOut)
|
humlet |
12:6ddadcbbdca2
|
183
|
{
|
humlet |
11:8c1d44595620
|
184
|
int ch = i2c_get_channel(obj);
|
humlet |
11:8c1d44595620
|
185
|
i2c_transfer[ch].cmd = waitSI;
|
humlet |
11:8c1d44595620
|
186
|
i2cRtos_wait_and_see(obj, ch, tmOut);
|
humlet |
9:65aae53a34de
|
187
|
}
|
humlet |
9:65aae53a34de
|
188
|
|
humlet |
9:65aae53a34de
|
189
|
|
humlet |
9:65aae53a34de
|
190
|
int i2cRtos_read(i2c_t *obj, int address, char *data, int length, int stop)
|
humlet |
9:65aae53a34de
|
191
|
{
|
humlet |
12:6ddadcbbdca2
|
192
|
//gpio_write(&gpio[1], 1);
|
humlet |
11:8c1d44595620
|
193
|
int stat = i2c_start(obj);
|
humlet |
11:8c1d44595620
|
194
|
if ((stat != 0x10) && (stat != 0x08)) {
|
humlet |
9:65aae53a34de
|
195
|
i2c_stop(obj);
|
humlet |
11:8c1d44595620
|
196
|
return stat;
|
humlet |
9:65aae53a34de
|
197
|
}
|
humlet |
12:6ddadcbbdca2
|
198
|
//gpio_write(&gpio[1], 0);
|
humlet |
9:65aae53a34de
|
199
|
int ch = i2c_get_channel(obj);
|
humlet |
12:6ddadcbbdca2
|
200
|
struct I2cIsrTransfer* tr = &(i2c_transfer[ch]); // evilive fill it locally and then copy it in one go to (volatile) mem?
|
humlet |
9:65aae53a34de
|
201
|
tr->obj=obj;
|
humlet |
9:65aae53a34de
|
202
|
tr->cmd=readMst;
|
humlet |
9:65aae53a34de
|
203
|
tr->len=length;
|
humlet |
9:65aae53a34de
|
204
|
tr->cnt=-1;
|
humlet |
9:65aae53a34de
|
205
|
tr->rData=data;
|
humlet |
9:65aae53a34de
|
206
|
I2C_DAT(obj) = address | 0x01;
|
humlet |
11:8c1d44595620
|
207
|
i2cRtos_wait_and_see(obj, ch,2+(length>>2)); // timeout (2+len/4)ms
|
humlet |
11:8c1d44595620
|
208
|
stat = tr->stat;
|
humlet |
12:6ddadcbbdca2
|
209
|
//gpio_write(&gpio[1], 1);
|
humlet |
11:8c1d44595620
|
210
|
if(stat || stop) i2c_stop(obj);
|
humlet |
12:6ddadcbbdca2
|
211
|
//gpio_write(&gpio[1], 0);
|
humlet |
11:8c1d44595620
|
212
|
return stat;
|
humlet |
9:65aae53a34de
|
213
|
}
|
humlet |
9:65aae53a34de
|
214
|
|
humlet |
9:65aae53a34de
|
215
|
int i2cRtos_write(i2c_t *obj, int address, const char *data, int length, int stop)
|
humlet |
9:65aae53a34de
|
216
|
{
|
humlet |
12:6ddadcbbdca2
|
217
|
//gpio_write(&gpio[1], 1);
|
humlet |
9:65aae53a34de
|
218
|
int status = i2c_start(obj);
|
humlet |
9:65aae53a34de
|
219
|
if ((status != 0x10) && (status != 0x08)) {
|
humlet |
9:65aae53a34de
|
220
|
i2c_stop(obj);
|
humlet |
9:65aae53a34de
|
221
|
return status;
|
humlet |
9:65aae53a34de
|
222
|
}
|
humlet |
12:6ddadcbbdca2
|
223
|
//gpio_write(&gpio[1], 0);
|
humlet |
12:6ddadcbbdca2
|
224
|
|
humlet |
9:65aae53a34de
|
225
|
int ch = i2c_get_channel(obj);
|
humlet |
12:6ddadcbbdca2
|
226
|
struct I2cIsrTransfer* tr = &(i2c_transfer[ch]); // evilive fill it locally and then copy it in one go to (volatile) mem?
|
humlet |
12:6ddadcbbdca2
|
227
|
tr->obj = obj;
|
humlet |
12:6ddadcbbdca2
|
228
|
tr->cmd = writeMst;
|
humlet |
12:6ddadcbbdca2
|
229
|
tr->len = length;
|
humlet |
12:6ddadcbbdca2
|
230
|
tr->cnt = -1;
|
humlet |
12:6ddadcbbdca2
|
231
|
tr->wData = data;
|
humlet |
9:65aae53a34de
|
232
|
I2C_DAT(obj) = address & 0xfe;
|
humlet |
11:8c1d44595620
|
233
|
i2cRtos_wait_and_see(obj, ch, 2+(length>>2)); // timeout (2+len/4)ms
|
humlet |
12:6ddadcbbdca2
|
234
|
//i2c_clear_SI(obj); // ... why? Also in official lib ... I guess this is the "write instead of start" bug
|
humlet |
9:65aae53a34de
|
235
|
status = tr->stat;
|
humlet |
12:6ddadcbbdca2
|
236
|
//gpio_write(&gpio[1], 1);
|
humlet |
9:65aae53a34de
|
237
|
if(status || stop) i2c_stop(obj);
|
humlet |
12:6ddadcbbdca2
|
238
|
//gpio_write(&gpio[1], 0);
|
humlet |
9:65aae53a34de
|
239
|
return status;
|
humlet |
9:65aae53a34de
|
240
|
}
|
humlet |
9:65aae53a34de
|
241
|
|
humlet |
9:65aae53a34de
|
242
|
int i2cRtos_byte_read(i2c_t *obj, int last)
|
humlet |
9:65aae53a34de
|
243
|
{
|
humlet |
9:65aae53a34de
|
244
|
if(last) {
|
humlet |
9:65aae53a34de
|
245
|
i2c_conclr(obj, 0, 0, 0, 1); // send a NOT ACK
|
humlet |
9:65aae53a34de
|
246
|
} else {
|
humlet |
9:65aae53a34de
|
247
|
i2c_conset(obj, 0, 0, 0, 1); // send a ACK
|
humlet |
9:65aae53a34de
|
248
|
}
|
humlet |
11:8c1d44595620
|
249
|
i2cRtos_waitSI(obj, 2);
|
humlet |
9:65aae53a34de
|
250
|
return (I2C_DAT(obj) & 0xff);
|
humlet |
9:65aae53a34de
|
251
|
}
|
humlet |
9:65aae53a34de
|
252
|
|
humlet |
9:65aae53a34de
|
253
|
int i2cRtos_byte_write(i2c_t *obj, int data)
|
humlet |
9:65aae53a34de
|
254
|
{
|
humlet |
9:65aae53a34de
|
255
|
I2C_DAT(obj) = (data & 0xff);
|
humlet |
11:8c1d44595620
|
256
|
i2cRtos_waitSI(obj, 2);
|
humlet |
9:65aae53a34de
|
257
|
int stat=i2c_status(obj);
|
humlet |
9:65aae53a34de
|
258
|
return (stat==0x18 || stat==0x28 || stat==0x40 || stat==0xb8);
|
humlet |
9:65aae53a34de
|
259
|
}
|
humlet |
9:65aae53a34de
|
260
|
|
humlet |
9:65aae53a34de
|
261
|
|
humlet |
13:530968937ccb
|
262
|
inline int i2cRtos_stop(i2c_t *obj) {
|
humlet |
13:530968937ccb
|
263
|
i2c_conset(obj, 0, 1, 0, 0);
|
humlet |
13:530968937ccb
|
264
|
i2c_clear_SI(obj);
|
humlet |
13:530968937ccb
|
265
|
|
humlet |
13:530968937ccb
|
266
|
uint32_t t0=us_ticker_read();
|
humlet |
13:530968937ccb
|
267
|
uint32_t dt=0;
|
humlet |
13:530968937ccb
|
268
|
while((I2C_CONSET(obj) & (1 << 4)) && dt<23){
|
humlet |
13:530968937ccb
|
269
|
dt = us_ticker_read() - t0;
|
humlet |
13:530968937ccb
|
270
|
}
|
humlet |
13:530968937ccb
|
271
|
return dt<23;
|
humlet |
13:530968937ccb
|
272
|
}
|
humlet |
13:530968937ccb
|
273
|
|
humlet |
13:530968937ccb
|
274
|
|
humlet |
9:65aae53a34de
|
275
|
#if DEVICE_I2CSLAVE
|
humlet |
9:65aae53a34de
|
276
|
|
humlet |
9:65aae53a34de
|
277
|
|
humlet |
9:65aae53a34de
|
278
|
int i2cRtos_slave_receive(i2c_t *obj, uint32_t tmOut)
|
humlet |
9:65aae53a34de
|
279
|
{
|
humlet |
9:65aae53a34de
|
280
|
int retval = i2c_slave_receive(obj);
|
humlet |
9:65aae53a34de
|
281
|
//check for pending requests
|
humlet |
9:65aae53a34de
|
282
|
if(retval)return retval; // there is one => bail out
|
humlet |
9:65aae53a34de
|
283
|
// No request? Wait for it!
|
humlet |
11:8c1d44595620
|
284
|
i2cRtos_waitSI(obj, tmOut);
|
humlet |
9:65aae53a34de
|
285
|
// check again for pending requests
|
humlet |
9:65aae53a34de
|
286
|
return i2c_slave_receive(obj);
|
humlet |
9:65aae53a34de
|
287
|
}
|
humlet |
9:65aae53a34de
|
288
|
|
humlet |
9:65aae53a34de
|
289
|
int i2cRtos_slave_read(i2c_t *obj, char *data, int length)
|
humlet |
9:65aae53a34de
|
290
|
{
|
humlet |
9:65aae53a34de
|
291
|
int ch = i2c_get_channel(obj);
|
humlet |
12:6ddadcbbdca2
|
292
|
struct I2cIsrTransfer* tr = &(i2c_transfer[ch]); // evilive fill it locally and then copy it in one go to (volatile) mem?
|
humlet |
9:65aae53a34de
|
293
|
tr->obj=obj;
|
humlet |
9:65aae53a34de
|
294
|
tr->cmd=readSlv;
|
humlet |
9:65aae53a34de
|
295
|
tr->len=length;
|
humlet |
9:65aae53a34de
|
296
|
tr->cnt=-1;
|
humlet |
9:65aae53a34de
|
297
|
tr->rData=data;
|
humlet |
10:e3d6c92ff222
|
298
|
i2cRtos_wait_and_see(obj, ch, 2+(length>>2)); // timeout (1+len/4)ms
|
humlet |
9:65aae53a34de
|
299
|
if(tr->stat != 0xa0) {
|
humlet |
9:65aae53a34de
|
300
|
i2c_stop(obj);
|
humlet |
9:65aae53a34de
|
301
|
}
|
humlet |
11:8c1d44595620
|
302
|
i2c_clear_SI(obj); // ... why? Also in official lib ... stops keeping scl low
|
humlet |
9:65aae53a34de
|
303
|
return tr->cnt; // same weird return as in official lib
|
humlet |
9:65aae53a34de
|
304
|
}
|
humlet |
9:65aae53a34de
|
305
|
|
humlet |
9:65aae53a34de
|
306
|
int i2cRtos_slave_write(i2c_t *obj, const char *data, int length)
|
humlet |
9:65aae53a34de
|
307
|
{
|
humlet |
9:65aae53a34de
|
308
|
if(length <= 0) {
|
humlet |
9:65aae53a34de
|
309
|
return(0);
|
humlet |
9:65aae53a34de
|
310
|
}
|
humlet |
9:65aae53a34de
|
311
|
int ch = i2c_get_channel(obj);
|
humlet |
12:6ddadcbbdca2
|
312
|
struct I2cIsrTransfer* tr = &(i2c_transfer[ch]); // evilive fill it locally and then copy it in one go to (volatile) mem?
|
humlet |
9:65aae53a34de
|
313
|
tr->obj=obj;
|
humlet |
9:65aae53a34de
|
314
|
tr->cmd=writeSlv;
|
humlet |
9:65aae53a34de
|
315
|
tr->len=length;
|
humlet |
9:65aae53a34de
|
316
|
tr->cnt=0;
|
humlet |
9:65aae53a34de
|
317
|
tr->wData=data;
|
humlet |
9:65aae53a34de
|
318
|
I2C_DAT(obj) = data[0];
|
humlet |
11:8c1d44595620
|
319
|
i2cRtos_wait_and_see(obj, ch, 2+(length>>2)); // timeout (1+len/4)ms
|
humlet |
9:65aae53a34de
|
320
|
int status = tr->stat;
|
humlet |
9:65aae53a34de
|
321
|
if(status!=0xC0 && status!=0xC8) {
|
humlet |
9:65aae53a34de
|
322
|
i2c_stop(obj);
|
humlet |
9:65aae53a34de
|
323
|
}
|
humlet |
11:8c1d44595620
|
324
|
i2c_clear_SI(obj); // ... why? Also in official lib ... stops keeping scl low
|
humlet |
9:65aae53a34de
|
325
|
return tr->cnt;
|
humlet |
9:65aae53a34de
|
326
|
}
|
humlet |
9:65aae53a34de
|
327
|
|
humlet |
11:8c1d44595620
|
328
|
|
humlet |
11:8c1d44595620
|
329
|
// setup semaphores and hook in ISRs
|
humlet |
11:8c1d44595620
|
330
|
void i2cRtos_init(i2c_t *obj, PinName sda, PinName scl)
|
humlet |
11:8c1d44595620
|
331
|
{
|
humlet |
13:530968937ccb
|
332
|
|
humlet |
11:8c1d44595620
|
333
|
static int called=0;
|
humlet |
11:8c1d44595620
|
334
|
if(!called) {
|
humlet |
11:8c1d44595620
|
335
|
gpio_init(&gpio[0], p15, PIN_OUTPUT);
|
humlet |
11:8c1d44595620
|
336
|
gpio_init(&gpio[1], p16, PIN_OUTPUT);
|
humlet |
11:8c1d44595620
|
337
|
}
|
humlet |
11:8c1d44595620
|
338
|
called = 1;
|
humlet |
11:8c1d44595620
|
339
|
gpio_write(&gpio[0], 0);
|
humlet |
11:8c1d44595620
|
340
|
gpio_write(&gpio[1], 0);
|
humlet |
13:530968937ccb
|
341
|
|
humlet |
11:8c1d44595620
|
342
|
i2c_init(obj,sda,scl);
|
humlet |
11:8c1d44595620
|
343
|
uint32_t ch = i2c_get_channel(obj);
|
humlet |
11:8c1d44595620
|
344
|
#if defined(TARGET_LPC1768) || defined(TARGET_LPC2368)
|
humlet |
11:8c1d44595620
|
345
|
static osSemaphoreDef(i2cIsrDrvSem_ch0);
|
humlet |
11:8c1d44595620
|
346
|
static osSemaphoreDef(i2cIsrDrvSem_ch1);
|
humlet |
11:8c1d44595620
|
347
|
switch(ch) {
|
humlet |
11:8c1d44595620
|
348
|
case 0:
|
humlet |
11:8c1d44595620
|
349
|
isrIrqSem[ch].irq = I2C1_IRQn;
|
humlet |
11:8c1d44595620
|
350
|
NVIC_SetVector(I2C1_IRQn, (uint32_t)i2cRtos_isr_ch0);
|
humlet |
11:8c1d44595620
|
351
|
isrIrqSem[ch].sem = osSemaphoreCreate(osSemaphore(i2cIsrDrvSem_ch0), 1);
|
humlet |
11:8c1d44595620
|
352
|
break;
|
humlet |
11:8c1d44595620
|
353
|
case 1:
|
humlet |
11:8c1d44595620
|
354
|
isrIrqSem[ch].irq = I2C2_IRQn;
|
humlet |
11:8c1d44595620
|
355
|
NVIC_SetVector(I2C2_IRQn, (uint32_t)i2cRtos_isr_ch1);
|
humlet |
11:8c1d44595620
|
356
|
isrIrqSem[ch].sem = osSemaphoreCreate(osSemaphore(i2cIsrDrvSem_ch1), 1);
|
humlet |
11:8c1d44595620
|
357
|
break;
|
humlet |
11:8c1d44595620
|
358
|
}
|
humlet |
11:8c1d44595620
|
359
|
osSemaphoreWait(isrIrqSem[ch].sem, osWaitForever);
|
humlet |
11:8c1d44595620
|
360
|
#elif defined(TARGET_LPC11U24)
|
humlet |
11:8c1d44595620
|
361
|
static osSemaphoreDef(i2cIsrDrvSem_ch1);
|
humlet |
11:8c1d44595620
|
362
|
isrIrqSem[ch].irq = I2C_IRQn;
|
humlet |
11:8c1d44595620
|
363
|
NVIC_SetVector(I2C_IRQn, (uint32_t)i2cRtos_isr_ch1);
|
humlet |
11:8c1d44595620
|
364
|
isrIrqSem[ch].sem = osSemaphoreCreate(osSemaphore(i2cIsrDrvSem_ch1), 1);
|
humlet |
11:8c1d44595620
|
365
|
osSemaphoreWait(isrIrqSem[ch].sem, osWaitForever);
|
humlet |
11:8c1d44595620
|
366
|
#else
|
humlet |
11:8c1d44595620
|
367
|
#error "Dial911 i2cRtos_init: Unsupported HW"
|
humlet |
11:8c1d44595620
|
368
|
#endif
|
humlet |
11:8c1d44595620
|
369
|
}
|
humlet |
9:65aae53a34de
|
370
|
#endif
|
humlet |
9:65aae53a34de
|
371
|
#endif
|