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