1 | #include "STM32_I2C.h"
|
2 | #include "STM32_DriverInterna.h"
|
3 | #include <stm32f10x.h>
|
4 | #ifdef DEBUG
|
5 | #include <stdio.h>
|
6 | #endif
|
7 |
|
8 | #define Core__Frequency 72000000
|
9 |
|
10 | #define I2C_NO_MUTEX
|
11 | #define I2C1__active //port0.0 SDA1, port0.1 SCL1
|
12 | //#define I2C2__active //port0.10 SDA2, port0.11 SCL2
|
13 |
|
14 |
|
15 |
|
16 |
|
17 | I2Cslot::I2Cslot(unsigned char address, unsigned char port)
|
18 | {
|
19 | this->address = address;
|
20 | this->port = port - 1;
|
21 | }
|
22 |
|
23 | extern "C" {
|
24 |
|
25 | void I2C1_EV_IRQHandler(void);
|
26 | void I2C2_EV_IRQHandler(void);
|
27 |
|
28 | void I2C1_ER_IRQHandler(void);
|
29 | void I2C2_ER_IRQHandler(void);
|
30 |
|
31 |
|
32 | struct {
|
33 | unsigned char *pMsg;
|
34 | volatile char error;
|
35 | unsigned char count;
|
36 | unsigned char address;
|
37 | #ifndef I2C_NO_MUTEX
|
38 | CTL_MUTEX_t mutex;
|
39 | #endif
|
40 | }I2C[1];
|
41 | }
|
42 |
|
43 | void I2Cslot::init()
|
44 | {
|
45 | #ifdef I2C1__active
|
46 | I2C1->CR2 = (3 << 8) | 0x24; // set APB clock 36MHz and [enable IRQs : Error, Buffer, Event I2C1->CR2 = (7 << 8)]
|
47 | I2C1->CCR = (1 << 15)|(1<<14)|27; // enable fast mode 19:9
|
48 | I2C1->TRISE = 11;
|
49 | I2C1->CR1 = 1; //I2C enable
|
50 | #ifndef I2C_NO_MUTEX
|
51 | ctl_mutex_init(&I2C[0].mutex);
|
52 | #endif
|
53 | ctl_set_isr(31, 10, I2C1_EV_IRQHandler, 0);
|
54 | ctl_unmask_isr(31);
|
55 | ctl_set_isr(32, 10, I2C1_ER_IRQHandler, 0);
|
56 | ctl_unmask_isr(32);
|
57 | #endif
|
58 | #ifdef I2C2__active
|
59 | I2C2->CR2 = (7 << 8) | 0x24; // set APB clock 36MHz and enable IRQs : Error, Buffer, Event
|
60 | I2C2->CCR = (1 << 15)|(1<<14)|23; // enable fast mode 19:9
|
61 | I2C2->TRISE = 11;
|
62 | I2C2->CR1 = 1; //I2C enable
|
63 | ctl_mutex_init(&I2C[1].mutex);
|
64 | ctl_set_isr(33, 10, I2C2_EV_IRQHandler, 0);
|
65 | ctl_unmask_isr(31);
|
66 | ctl_set_isr(34, 10, I2C2_ER_IRQHandler, 0);
|
67 | ctl_unmask_isr(32);
|
68 | #endif
|
69 | }
|
70 |
|
71 |
|
72 | int I2Cslot::send(unsigned char *pMsg)
|
73 | {
|
74 | #ifdef DEBUG
|
75 | printf("I2C: %d Bytes to %X\n", pMsg[0], address);
|
76 | #endif
|
77 | #ifndef I2C_NO_MUTEX
|
78 | ctl_mutex_lock(&I2C[port].mutex, CTL_TIMEOUT_NONE, 0);
|
79 | #endif
|
80 | I2C[port].pMsg = pMsg; //adjust pointer to msg
|
81 | I2C[port].error = 1; //initialize error
|
82 | I2C[port].count = 1; //initialize counter
|
83 | I2C[port].address = address;
|
84 | switch(port)
|
85 | {
|
86 | #ifdef I2C1__active
|
87 | case 0:
|
88 | I2C1->CR1 |= 0x100; //generate start condition
|
89 | WaitStatus_I2C1; //wait for hardware to complete the operation
|
90 | break;
|
91 | #endif
|
92 | #ifdef I2C2__active
|
93 | case 1:
|
94 | I2C2->CR2 |= 0x100; //generate start condition
|
95 | WaitStatus_I2C2; //wait for hardware to complete the operation
|
96 | break;
|
97 | #endif
|
98 | default:
|
99 | while(1); //trying to access inactive port
|
100 | }
|
101 | #ifdef DEBUG
|
102 | if(I2C[port].error)
|
103 | printf("I2Cerror: %X", I2C[port].error);
|
104 | #endif
|
105 | #ifndef I2C_NO_MUTEX
|
106 | ctl_mutex_unlock(&I2C[port].mutex);
|
107 | #endif
|
108 | return I2C[port].error;
|
109 | }
|
110 |
|
111 | int I2Cslot::recv(unsigned char *pMsg)
|
112 | {
|
113 | address++;
|
114 | int temp = send(pMsg);
|
115 | address--;
|
116 | return (temp);
|
117 | }
|
118 |
|
119 | int I2Cslot::send_sync(unsigned char *pMsg)
|
120 | {
|
121 | #ifdef DEBUG
|
122 | printf("I2C%d: %d Bytes to %X\n", port, pMsg[0], address);
|
123 | #endif
|
124 | #ifndef I2C_NO_MUTEX
|
125 | ctl_mutex_lock(&I2C[port].mutex, CTL_TIMEOUT_NONE, 0);
|
126 | #endif
|
127 | I2C[port].pMsg = pMsg; //adjust pointer to msg
|
128 | I2C[port].error = 1; //initialize error
|
129 | I2C[port].count = 1; //initialize counter
|
130 | I2C[port].address = address;
|
131 | switch(port)
|
132 | {
|
133 | #ifdef I2C1__active
|
134 | case 0:
|
135 | I2C1->CR1 = 0x101; //generate start condition
|
136 | break;
|
137 | #endif
|
138 | #ifdef I2C2__active
|
139 | case 1:
|
140 | I2C2->CR1 = 0x101; //generate start condition
|
141 | break;
|
142 | #endif
|
143 | default:
|
144 | while(1); //trying to access inactive port
|
145 | }
|
146 |
|
147 |
|
148 | while(I2C[port].error == 1)
|
149 | ;
|
150 |
|
151 |
|
152 | #ifdef DEBUG
|
153 | if(I2C[port].error)
|
154 | printf("I2C%derror: %X", port, I2C[port].error);
|
155 | #endif
|
156 | #ifndef I2C_NO_MUTEX
|
157 | ctl_mutex_unlock(&I2C[port].mutex);
|
158 | #endif
|
159 | return I2C[port].error;
|
160 | }
|
161 |
|
162 | int I2Cslot::recv_sync(unsigned char *pMsg)
|
163 | {
|
164 | address++;
|
165 | int temp = send_sync(pMsg);
|
166 | address--;
|
167 | return (temp);
|
168 | }
|
169 |
|
170 | extern "C" {
|
171 | #ifdef I2C1__active
|
172 | void I2C1_EV_IRQHandler (void)
|
173 | {
|
174 | ctl_enter_isr();
|
175 |
|
176 | static int status2 = 0;
|
177 | int status1 = I2C1->SR1;
|
178 |
|
179 |
|
180 | if(status1 & 0x01) // start bit was send
|
181 | {
|
182 | I2C1->DR = I2C[0].address; // first transmit the address
|
183 | }
|
184 | else if( status1 & 0x02 ) // address transmitted and ACK received
|
185 | {
|
186 | status2 = I2C1->SR2; // read 2nd status register to clear it
|
187 | if( ~status2 & 0x04 ) // Receiver mode, determine ACK return
|
188 | {
|
189 | if( I2C[0].pMsg[0] > 1 ) // there's more than one byte to receive, set ACK return bit
|
190 | I2C1->CR1 = 0x401;
|
191 | else
|
192 | I2C1->CR1 = 0x201; // else there is only one byte to be received, set the STOP bit
|
193 | }
|
194 | }
|
195 |
|
196 | if ( status1 & 0x84 ) // if BTF or TxE bit is set we need to write/read a new byte
|
197 | {
|
198 | if( status2 & 0x04 ) // write if in transmitter mode
|
199 | {
|
200 | if( I2C[0].count <= I2C[0].pMsg[0] )
|
201 | { // if not all bytes have been transmitted yet, keep on pushing
|
202 | I2C1->DR = I2C[0].pMsg[I2C[0].count];
|
203 | I2C[0].count++;
|
204 | }
|
205 | else // the last byte was transmitted, shut down the interface
|
206 | {
|
207 | I2C[0].error = 0; // we done
|
208 | I2C1->CR1 = 0x201; // set stop bit
|
209 | StatusSet_I2C1;
|
210 | }
|
211 | }
|
212 | else // else in receiver mode
|
213 | { // read the byte just received
|
214 | I2C[0].pMsg[I2C[0].count] = I2C1->DR;
|
215 | I2C[0].count++;
|
216 | if( I2C[0].count == I2C[0].pMsg[0] )
|
217 | I2C1->CR1 = 0x201; // clear the ACK bit and Set the STOP bit for the next byte to be received
|
218 | else if( I2C[0].count > I2C[0].pMsg[0] )
|
219 | {
|
220 | I2C[0].error = 0; // we done
|
221 | StatusSet_I2C1;
|
222 | }
|
223 | }
|
224 | }
|
225 |
|
226 | ctl_exit_isr();
|
227 | }
|
228 |
|
229 | void I2C1_ER_IRQHandler(void)
|
230 | {
|
231 | ctl_enter_isr();
|
232 |
|
233 | int err = I2C1->SR1;
|
234 | I2C1->SR1 = 0; // write a zero to clear all flags
|
235 | if( err & 0x400 ) // NACK received
|
236 | {
|
237 | I2C1->CR1 = 0x201; // set a stop
|
238 | I2C[0].error = 0xFE;
|
239 | StatusSet_I2C1;
|
240 | }
|
241 | if( err & 0x200 ) // arbitration lost
|
242 | {
|
243 | I2C[0].error = 0xFF;
|
244 | StatusSet_I2C1;
|
245 | }
|
246 |
|
247 | if( I2C[0].count > I2C[0].pMsg[0] ) // indicates that the transfer was completed but a NACK on last byte? possible :/
|
248 | while(1);
|
249 |
|
250 | ctl_exit_isr();
|
251 | }
|
252 | #endif
|
253 | }
|