1 /**
2 * \file
3 *
4 * \brief I2C Master Interrupt Driver for SAMB
5 *
6 * Copyright (C) 2015-2016 Atmel Corporation. All rights reserved.
7 *
8 * \asf_license_start
9 *
10 * \page License
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright notice,
16 * this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright notice,
19 * this list of conditions and the following disclaimer in the documentation
20 * and/or other materials provided with the distribution.
21 *
22 * 3. The name of Atmel may not be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * 4. This software may only be redistributed and used in connection with an
26 * Atmel microcontroller product.
27 *
28 * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
29 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
31 * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
32 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
36 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
37 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 *
40 * \asf_license_stop
41 *
42 */
43 /*
44 * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
45 */
46
47 #include "i2c_master_interrupt.h"
48
49 void *_i2c_instances;
50
51 /**
52 * \internal
53 * Read next data. Used by interrupt handler to get next data byte from slave.
54 *
55 * \param[in,out] module Pointer to software module structure
56 */
_i2c_master_read(struct i2c_master_module * const module)57 static void _i2c_master_read(
58 struct i2c_master_module *const module)
59 {
60 /* Sanity check arguments. */
61 Assert(module);
62 Assert(module->hw);
63
64 I2c *const i2c_module = module->hw;
65
66 /* Find index to save next value in buffer */
67 uint16_t buffer_index = module->buffer_length - module->buffer_remaining;
68
69 module->buffer_remaining--;
70
71 module->buffer[buffer_index] = i2c_module->RECEIVE_DATA.reg;
72 }
73
74 /**
75 * \internal
76 *
77 * Write next data. Used by interrupt handler to send next data byte to slave.
78 *
79 * \param[in,out] module Pointer to software module structure
80 */
_i2c_master_write(struct i2c_master_module * const module)81 static void _i2c_master_write(struct i2c_master_module *const module)
82 {
83 /* Sanity check arguments. */
84 Assert(module);
85 Assert(module->hw);
86
87 I2c *const i2c_module = module->hw;
88
89 /* Find index to get next byte in buffer */
90 volatile uint16_t buffer_index = module->buffer_length - module->buffer_remaining;
91
92 module->buffer_remaining--;
93
94 /* Write byte from buffer to slave */
95 i2c_module->TRANSMIT_DATA.reg = module->buffer[buffer_index];
96
97 if (module->buffer_remaining <= 0) {
98 i2c_module->TX_INTERRUPT_MASK.reg = I2C_TX_INTERRUPT_MASK_TX_FIFO_EMPTY_MASK;
99 }
100 }
101
102
103 /**
104 * \brief Registers callback for the specified callback type
105 *
106 * Associates the given callback function with the
107 * specified callback type.
108 *
109 * To enable the callback, the \ref i2c_master_enable_callback function
110 * must be used.
111 *
112 * \param[in,out] module Pointer to the software module struct
113 * \param[in] callback Pointer to the function desired for the
114 * specified callback
115 * \param[in] callback_type Callback type to register
116 */
i2c_master_register_callback(struct i2c_master_module * const module,const i2c_master_callback_t callback,enum i2c_master_callback callback_type)117 void i2c_master_register_callback(
118 struct i2c_master_module *const module,
119 const i2c_master_callback_t callback,
120 enum i2c_master_callback callback_type)
121 {
122 /* Sanity check */
123 Assert(module);
124 Assert(module->hw);
125 Assert(callback);
126
127 /* Register callback */
128 module->callbacks[callback_type] = callback;
129
130 /* Set corresponding bit to set callback as registered */
131 module->registered_callback |= (1 << callback_type);
132 }
133
134 /**
135 * \brief Unregisters callback for the specified callback type
136 *
137 * When called, the currently registered callback for the given callback type
138 * will be removed.
139 *
140 * \param[in,out] module Pointer to the software module struct
141 * \param[in] callback_type Specifies the callback type to unregister
142 */
i2c_master_unregister_callback(struct i2c_master_module * const module,enum i2c_master_callback callback_type)143 void i2c_master_unregister_callback(
144 struct i2c_master_module *const module,
145 enum i2c_master_callback callback_type)
146 {
147 /* Sanity check */
148 Assert(module);
149 Assert(module->hw);
150
151 /* Register callback */
152 module->callbacks[callback_type] = NULL;
153
154 /* Clear corresponding bit to set callback as unregistered */
155 module->registered_callback &= ~(1 << callback_type);
156 }
157
158 /**
159 * \internal
160 * Starts a read packet operation.
161 *
162 * \param[in,out] module Pointer to software module struct
163 * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
164 *
165 * \return Status of starting reading I<SUP>2</SUP>C packet.
166 * \retval STATUS_OK If reading was started successfully
167 * \retval STATUS_BUSY If module is currently busy with another transfer
168 */
_i2c_master_read_packet(struct i2c_master_module * const module,struct i2c_master_packet * const packet)169 static enum status_code _i2c_master_read_packet(
170 struct i2c_master_module *const module,
171 struct i2c_master_packet *const packet)
172 {
173 /* Sanity check */
174 Assert(module);
175 Assert(module->hw);
176 Assert(packet);
177
178 I2c *const i2c_module = module->hw;
179
180 /* Save packet to software module */
181 module->buffer = packet->data;
182 module->buffer_remaining = packet->data_length;
183 module->transfer_direction = I2C_TRANSFER_READ;
184 module->status = STATUS_BUSY;
185
186 i2c_wait_for_idle(i2c_module);
187 /* Flush the FIFO */
188 i2c_module->I2C_FLUSH.reg = 1;
189 /* Enable I2C on bus (start condition) */
190 i2c_module->I2C_ONBUS.reg = I2C_ONBUS_ONBUS_ENABLE_1;
191 /* Set address and direction bit. Will send start command on bus */
192 i2c_module->TRANSMIT_DATA.reg = I2C_TRANSMIT_DATA_ADDRESS_FLAG_1 |
193 (packet->address << 1) | module->transfer_direction;
194 /* Enable interrupts */
195 i2c_module->RX_INTERRUPT_MASK.reg = I2C_RX_INTERRUPT_MASK_RX_FIFO_NOT_EMPTY_MASK;
196
197 return STATUS_OK;
198 }
199
200 /**
201 * \brief Initiates a read packet operation
202 *
203 * Reads a data packet from the specified slave address on the I<SUP>2</SUP>C
204 * bus. This is the non-blocking equivalent of \ref i2c_master_read_packet_wait.
205 *
206 * \param[in,out] module Pointer to software module struct
207 * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
208 *
209 * \return Status of starting reading I<SUP>2</SUP>C packet.
210 * \retval STATUS_OK If reading was started successfully
211 * \retval STATUS_BUSY If module is currently busy with another transfer
212 */
i2c_master_read_packet_job(struct i2c_master_module * const module,struct i2c_master_packet * const packet)213 enum status_code i2c_master_read_packet_job(
214 struct i2c_master_module *const module,
215 struct i2c_master_packet *const packet)
216 {
217 /* Sanity check */
218 Assert(module);
219 Assert(module->hw);
220 Assert(packet);
221
222 /* Check if the I2C module is busy with a job */
223 if (module->buffer_remaining > 0) {
224 return STATUS_BUSY;
225 }
226
227 /* Make sure we send STOP */
228 module->no_stop = false;
229 /* Start reading */
230 return _i2c_master_read_packet(module, packet);
231 }
232
233 /**
234 * \brief Initiates a read packet operation without sending a STOP condition when done
235 *
236 * Reads a data packet from the specified slave address on the I<SUP>2</SUP>C bus without
237 * sending a stop condition, thus retaining ownership of the bus when done.
238 * To end the transaction, a \ref i2c_master_read_packet_wait "read" or
239 * \ref i2c_master_write_packet_wait "write" with stop condition must be
240 * performed.
241 *
242 * This is the non-blocking equivalent of \ref i2c_master_read_packet_wait_no_stop.
243 *
244 * \param[in,out] module Pointer to software module struct
245 * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
246 *
247 * \return Status of starting reading I<SUP>2</SUP>C packet.
248 * \retval STATUS_OK If reading was started successfully
249 * \retval STATUS_BUSY If module is currently busy with another operation
250 */
i2c_master_read_packet_job_no_stop(struct i2c_master_module * const module,struct i2c_master_packet * const packet)251 enum status_code i2c_master_read_packet_job_no_stop(
252 struct i2c_master_module *const module,
253 struct i2c_master_packet *const packet)
254 {
255 /* Sanity check */
256 Assert(module);
257 Assert(module->hw);
258 Assert(packet);
259
260 /* Check if the I2C module is busy with a job */
261 if (module->buffer_remaining > 0) {
262 return STATUS_BUSY;
263 }
264
265 /* Make sure we don't send STOP */
266 module->no_stop = true;
267 /* Start reading */
268 return _i2c_master_read_packet(module, packet);
269 }
270
271
272 /**
273 * \internal Initiates a write packet operation
274 *
275 * \param[in,out] module Pointer to software module struct
276 * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
277 *
278 * \return Status of starting writing I<SUP>2</SUP>C packet job.
279 * \retval STATUS_OK If writing was started successfully
280 * \retval STATUS_BUSY If module is currently busy with another transfer
281 */
_i2c_master_write_packet(struct i2c_master_module * const module,struct i2c_master_packet * const packet)282 static enum status_code _i2c_master_write_packet(
283 struct i2c_master_module *const module,
284 struct i2c_master_packet *const packet)
285 {
286 /* Sanity check */
287 Assert(module);
288 Assert(module->hw);
289 Assert(packet);
290
291 I2c *const i2c_module = module->hw;
292
293 /* Save packet to software module */
294 module->buffer = packet->data;
295 module->buffer_remaining = packet->data_length;
296 module->transfer_direction = I2C_TRANSFER_WRITE;
297 module->status = STATUS_BUSY;
298
299 /* Enable I2C on bus (start condition) */
300 i2c_module->I2C_ONBUS.reg = I2C_ONBUS_ONBUS_ENABLE_1;
301 /* Set address and direction bit, will send start command on bus */
302 i2c_module->TRANSMIT_DATA.reg = I2C_TRANSMIT_DATA_ADDRESS_FLAG_1 |
303 (packet->address << 1) | module->transfer_direction;
304 /* Enable interrupts */
305 i2c_module->TX_INTERRUPT_MASK.reg = I2C_TX_INTERRUPT_MASK_TX_FIFO_EMPTY_MASK;
306
307 return STATUS_OK;
308 }
309
310 /**
311 * \brief Initiates a write packet operation
312 *
313 * Writes a data packet to the specified slave address on the I<SUP>2</SUP>C
314 * bus. This is the non-blocking equivalent of \ref i2c_master_write_packet_wait.
315 *
316 * \param[in,out] module Pointer to software module struct
317 * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
318 *
319 * \return Status of starting writing I<SUP>2</SUP>C packet job.
320 * \retval STATUS_OK If writing was started successfully
321 * \retval STATUS_BUSY If module is currently busy with another transfer
322 */
i2c_master_write_packet_job(struct i2c_master_module * const module,struct i2c_master_packet * const packet)323 enum status_code i2c_master_write_packet_job(
324 struct i2c_master_module *const module,
325 struct i2c_master_packet *const packet)
326 {
327 /* Sanity check */
328 Assert(module);
329 Assert(module->hw);
330 Assert(packet);
331
332 /* Check if the I2C module is busy with another job. */
333 if (module->buffer_remaining > 0) {
334 return STATUS_BUSY;
335 }
336
337 /* Make sure we send STOP at end*/
338 module->no_stop = false;
339 /* Start write operation */
340 return _i2c_master_write_packet(module, packet);
341 }
342
343 /**
344 * \brief Initiates a write packet operation without sending a STOP condition when done
345 *
346 * Writes a data packet to the specified slave address on the I<SUP>2</SUP>C bus
347 * without sending a stop condition, thus retaining ownership of the bus when
348 * done. To end the transaction, a \ref i2c_master_read_packet_wait "read" or
349 * \ref i2c_master_write_packet_wait "write" with stop condition or sending
350 * a stop with the \ref i2c_master_send_stop function must be performed.
351 *
352 * This is the non-blocking equivalent of \ref i2c_master_write_packet_wait_no_stop.
353 *
354 * \param[in,out] module Pointer to software module struct
355 * \param[in,out] packet Pointer to I<SUP>2</SUP>C packet to transfer
356 *
357 * \return Status of starting writing I<SUP>2</SUP>C packet job.
358 * \retval STATUS_OK If writing was started successfully
359 * \retval STATUS_BUSY If module is currently busy with another
360 */
i2c_master_write_packet_job_no_stop(struct i2c_master_module * const module,struct i2c_master_packet * const packet)361 enum status_code i2c_master_write_packet_job_no_stop(
362 struct i2c_master_module *const module,
363 struct i2c_master_packet *const packet)
364 {
365 /* Sanity check */
366 Assert(module);
367 Assert(module->hw);
368 Assert(packet);
369
370 /* Check if the I2C module is busy with another job. */
371 if (module->buffer_remaining > 0) {
372 return STATUS_BUSY;
373 }
374
375 /* Do not send stop condition when done */
376 module->no_stop = true;
377 /* Start write operation */
378 return _i2c_master_write_packet(module, packet);
379 }
380
381 /**
382 * Interrupt handler for I<SUP>2</SUP>C master.
383 */
_i2c_master_isr_handler(void)384 void _i2c_master_isr_handler(void)
385 {
386 /* Get software module for callback handling */
387 struct i2c_master_module *module =
388 (struct i2c_master_module*)_i2c_instances;
389
390 Assert(module);
391
392 I2c *const i2c_module = module->hw;
393
394 /* Combine callback registered and enabled masks */
395 uint8_t callback_mask = module->enabled_callback &
396 module->registered_callback;
397
398 if ((module->buffer_length <= 0) && (module->buffer_remaining > 0)) {
399 module->buffer_length = module->buffer_remaining;
400 /* Check if buffer write is done */
401 } else if ((module->buffer_length > 0) && (module->buffer_remaining <= 0) &&
402 (module->status == STATUS_BUSY) &&
403 (module->transfer_direction == I2C_TRANSFER_WRITE)) {
404 /* Disable write interrupt flag */
405 i2c_module->TX_INTERRUPT_MASK.reg = 0;
406
407 module->buffer_length = 0;
408 module->status = STATUS_OK;
409
410 if (!module->no_stop) {
411 /* Send stop condition */
412 i2c_module->I2C_ONBUS.reg = I2C_ONBUS_ONBUS_ENABLE_0;
413 }
414
415 if (callback_mask & (1 << I2C_MASTER_CALLBACK_WRITE_COMPLETE)) {
416 module->callbacks[I2C_MASTER_CALLBACK_WRITE_COMPLETE](module);
417 }
418
419 /* Continue buffer write/read */
420 } else if ((module->buffer_length > 0) && (module->buffer_remaining > 0)){
421 if (module->transfer_direction == I2C_TRANSFER_WRITE) {
422 _i2c_master_write(module);
423 } else {
424 _i2c_master_read(module);
425 }
426 }
427
428 /* Check if read buffer transfer is complete */
429 if ((module->buffer_length > 0) && (module->buffer_remaining <= 0) &&
430 (module->status == STATUS_BUSY) &&
431 (module->transfer_direction == I2C_TRANSFER_READ)) {
432 /* Disable read interrupt flag */
433 i2c_module->RX_INTERRUPT_MASK.reg = 0;
434
435 module->buffer_length = 0;
436 module->status = STATUS_OK;
437
438 if (!module->no_stop) {
439 /* Send stop condition */
440 i2c_module->I2C_ONBUS.reg = I2C_ONBUS_ONBUS_ENABLE_0;
441 }
442
443 if ((callback_mask & (1 << I2C_MASTER_CALLBACK_READ_COMPLETE))
444 && (module->transfer_direction == I2C_TRANSFER_READ)) {
445 module->callbacks[I2C_MASTER_CALLBACK_READ_COMPLETE](module);
446 }
447 }
448 if (module->transfer_direction == I2C_TRANSFER_READ) {
449 if (module->hw == I2C0) {
450 NVIC_ClearPendingIRQ(I2C0_RX_IRQn);
451 } else if (module->hw == I2C1) {
452 NVIC_ClearPendingIRQ(I2C1_RX_IRQn);
453 }
454 } else {
455 if (module->hw == I2C0) {
456 NVIC_ClearPendingIRQ(I2C0_TX_IRQn);
457 } else if (module->hw == I2C1) {
458 NVIC_ClearPendingIRQ(I2C1_TX_IRQn);
459 }
460 }
461 }
462